summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/funcutils
diff options
context:
space:
mode:
authorBen Culkin <scorpress@gmail.com>2020-12-01 20:19:34 -0500
committerBen Culkin <scorpress@gmail.com>2020-12-01 20:19:34 -0500
commitfefd6eb2917b9a0856c247353545cc13876b6eda (patch)
tree374e2d31426accd3f00c6bbbff2ff75123d92da2 /base/src/main/java/bjc/utils/funcutils
parent03de62016afa4e392f32069ec28ad58ee38699da (diff)
An assortment of changes/new things
Diffstat (limited to 'base/src/main/java/bjc/utils/funcutils')
-rw-r--r--base/src/main/java/bjc/utils/funcutils/Callables.java60
-rw-r--r--base/src/main/java/bjc/utils/funcutils/ChainIterator.java54
-rw-r--r--base/src/main/java/bjc/utils/funcutils/FuncUtils.java34
-rw-r--r--base/src/main/java/bjc/utils/funcutils/Isomorphism.java59
-rw-r--r--base/src/main/java/bjc/utils/funcutils/IteratorUtils.java102
-rw-r--r--base/src/main/java/bjc/utils/funcutils/QueueBackedIterator.java36
-rw-r--r--base/src/main/java/bjc/utils/funcutils/Strategy.java81
7 files changed, 304 insertions, 122 deletions
diff --git a/base/src/main/java/bjc/utils/funcutils/Callables.java b/base/src/main/java/bjc/utils/funcutils/Callables.java
new file mode 100644
index 0000000..5895347
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcutils/Callables.java
@@ -0,0 +1,60 @@
+package bjc.utils.funcutils;
+
+import java.util.concurrent.*;
+import java.util.function.*;
+
+/**
+ * Utility function for dealing with callables and other things.
+ *
+ * @author Ben Culkin
+ *
+ */
+public class Callables
+{
+ /**
+ * Perform a 'bind' that appends a function to a callable.
+ *
+ * @param <Input> The type originally returned by the callable.
+ * @param <Output> The type returned by the function.
+ *
+ * @param call The original callable.
+ * @param func The function to use to transform the result.
+ *
+ * @return A callable which applies the given function to the result of them.
+ */
+ public static <Input, Output> Callable<Output> bind(
+ Callable<Input> call, Function<Input, Callable<Output>> func)
+ {
+ return () -> func.apply(call.call()).call();
+ }
+
+ /**
+ * Convert a normal function to a function on callables.
+ *
+ * @param <Input> The input to the function.
+ * @param <Output> The output from the function.
+ *
+ * @param func The function to convert.
+ *
+ * @return The function, made to work over callables.
+ */
+ public static <Input, Output> Function<Callable<Input>, Callable<Output>>
+ fmap(Function<Input, Output> func)
+ {
+ return (inp) -> () -> func.apply(inp.call());
+ }
+
+ /**
+ * Convert a future into a callable.
+ *
+ * @param <Output> The type returned by the future.
+ *
+ * @param fut The future to convert.
+ *
+ * @return A future which yields that value.
+ */
+ public static <Output> Callable<Output> obtain(Future<Output> fut)
+ {
+ return () -> fut.get();
+ }
+}
diff --git a/base/src/main/java/bjc/utils/funcutils/ChainIterator.java b/base/src/main/java/bjc/utils/funcutils/ChainIterator.java
new file mode 100644
index 0000000..36f94e5
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcutils/ChainIterator.java
@@ -0,0 +1,54 @@
+package bjc.utils.funcutils;
+
+import java.util.*;
+import java.util.function.*;
+
+/**
+ * A chain iterator. This is essentially flatMap in iterator form.
+ *
+ * @author bjculkin
+ *
+ * @param <T1>
+ * The type of the input values.
+ *
+ * @param <T2>
+ * The type of the output values.
+ */
+public class ChainIterator<T1, T2> implements Iterator<T2> {
+ private Iterator<T1> mainItr;
+ private Function<T1, Iterator<T2>> trans;
+
+ private Iterator<T2> curItr;
+
+ /**
+ * Create a new chain iterator.
+ *
+ * @param mainItr
+ * The main iterator for input.
+ *
+ * @param trans
+ * The transformation to use to produce the outputs.
+ */
+ public ChainIterator(Iterator<T1> mainItr, Function<T1, Iterator<T2>> trans) {
+ this.mainItr = mainItr;
+ this.trans = trans;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (curItr != null) {
+ return curItr.hasNext() ? true : mainItr.hasNext();
+ }
+
+ return mainItr.hasNext();
+ }
+
+ @Override
+ public T2 next() {
+ if (curItr == null || !curItr.hasNext()) {
+ curItr = trans.apply(mainItr.next());
+ }
+
+ return curItr.next();
+ }
+} \ No newline at end of file
diff --git a/base/src/main/java/bjc/utils/funcutils/FuncUtils.java b/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
index 70e521a..2c65876 100644
--- a/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
@@ -29,9 +29,12 @@ public class FuncUtils {
*
* @return The function transformed into a unary function returning a function.
*/
- public static <A, B, C> Function<A, Function<B, C>>
- curry2(final BiFunction<A, B, C> func) {
- return arg1 -> arg2 -> func.apply(arg1, arg2);
+ public static <A, B, C> Function<A, Function<B, C>> curry2(
+ final BiFunction<A, B, C> func)
+ {
+ return arg1 ->
+ arg2 ->
+ func.apply(arg1, arg2);
}
/**
@@ -43,14 +46,17 @@ public class FuncUtils {
* @param cons
* The action to perform.
*/
- public static void doTimes(final int nTimes, final Consumer<Integer> cons) {
- for (int i = 0; i < nTimes; i++) {
- cons.accept(i);
- }
+ public static void doTimes(
+ final int nTimes,
+ final Consumer<Integer> cons)
+ {
+ for (int i = 0; i < nTimes; i++) cons.accept(i);
}
/**
* Return an operator that executes until it converges.
+ *
+ * @param <T> The type the operator is on.
*
* @param op
* The operator to execute.
@@ -62,12 +68,15 @@ public class FuncUtils {
* @return The requested operator.
*/
public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op,
- final int maxTries) {
+ final int maxTries)
+ {
return converge(op, Object::equals, maxTries);
}
/**
* Return an operator that executes until it converges.
+ *
+ * @param <T> The type the operator is on.
*
* @param op
* The operator to execute.
@@ -81,11 +90,14 @@ public class FuncUtils {
*
* @return The requested operator.
*/
- public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op,
- final BiPredicate<T, T> converged, final int maxTries) {
+ public static <T> UnaryOperator<T> converge(
+ final UnaryOperator<T> op,
+ final BiPredicate<T, T> converged,
+ final int maxTries)
+ {
return val -> {
T newVal = op.apply(val);
- T oldVal;
+ T oldVal = newVal;
int tries = 0;
diff --git a/base/src/main/java/bjc/utils/funcutils/Isomorphism.java b/base/src/main/java/bjc/utils/funcutils/Isomorphism.java
deleted file mode 100644
index c219d7f..0000000
--- a/base/src/main/java/bjc/utils/funcutils/Isomorphism.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package bjc.utils.funcutils;
-
-import java.util.function.Function;
-
-/**
- * A pair of functions to transform between a pair of types.
- *
- * @author bjculkin
- *
- * @param <S>
- * The source type of the isomorphism.
- *
- * @param <D>
- * The destination type of isomorphism.
- */
-public class Isomorphism<S, D> {
- /* The function to the destination type. */
- private Function<S, D> toFunc;
- /* The function to the source type. */
- private Function<D, S> fromFunc;
-
- /**
- * Create a new isomorphism.
- *
- * @param to
- * The 'forward' function, from the source to the definition.
- *
- * @param from
- * The 'backward' function, from the definition to the source.
- */
- public Isomorphism(Function<S, D> to, Function<D, S> from) {
- toFunc = to;
- fromFunc = from;
- }
-
- /**
- * Apply the isomorphism forward.
- *
- * @param val
- * The source value.
- *
- * @return The destination value.
- */
- public D to(S val) {
- return toFunc.apply(val);
- }
-
- /**
- * Apply the isomorphism backward.
- *
- * @param val
- * The destination value.
- *
- * @return The source value.
- */
- public S from(D val) {
- return fromFunc.apply(val);
- }
-}
diff --git a/base/src/main/java/bjc/utils/funcutils/IteratorUtils.java b/base/src/main/java/bjc/utils/funcutils/IteratorUtils.java
index 8d51996..ea67295 100644
--- a/base/src/main/java/bjc/utils/funcutils/IteratorUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/IteratorUtils.java
@@ -3,7 +3,7 @@ package bjc.utils.funcutils;
import java.util.*;
import java.util.function.*;
-import bjc.data.ArrayIterator;
+import bjc.data.*;
/**
* Utility methods for dealing with iterators.
@@ -13,57 +13,9 @@ import bjc.data.ArrayIterator;
*/
public class IteratorUtils {
/**
- * A chain iterator. This is essentially flatMap in iterator form.
- *
- * @author bjculkin
- *
- * @param <T1>
- * The type of the input values.
- *
- * @param <T2>
- * The type of the output values.
- */
- public static class ChainIterator<T1, T2> implements Iterator<T2> {
- private Iterator<T1> mainItr;
- private Function<T1, Iterator<T2>> trans;
-
- private Iterator<T2> curItr;
-
- /**
- * Create a new chain iterator.
- *
- * @param mainItr
- * The main iterator for input.
- *
- * @param trans
- * The transformation to use to produce the outputs.
- */
- public ChainIterator(Iterator<T1> mainItr, Function<T1, Iterator<T2>> trans) {
- this.mainItr = mainItr;
- this.trans = trans;
- }
-
- @Override
- public boolean hasNext() {
- if (curItr != null) {
- return curItr.hasNext() ? true : mainItr.hasNext();
- }
-
- return mainItr.hasNext();
- }
-
- @Override
- public T2 next() {
- if (curItr == null || !curItr.hasNext()) {
- curItr = trans.apply(mainItr.next());
- }
-
- return curItr.next();
- }
- }
-
- /**
* Convert an iterator to an iterable.
+ *
+ * @param <E> The type being iterated over.
*
* @param itr
* The iterator to convert.
@@ -77,6 +29,8 @@ public class IteratorUtils {
/**
* Convert an iterable to an iterator.
*
+ * @param <E> The type being iterated over.
+ *
* @param itr
* The iterable to convert.
*
@@ -89,18 +43,23 @@ public class IteratorUtils {
/**
* Convert an array to an iterator.
*
+ * @param <E> The type being iterated over.
+ *
* @param parms
* The array to iterate over.
*
* @return An iterator over the provided array.
*/
@SafeVarargs
- public static <E> Iterator<E> AI(E... parms) {
+ public static <E> Iterator<E> I(E... parms) {
return new ArrayIterator<>(parms);
}
/**
* Create a chain iterator.
+ *
+ * @param <A> The initial type being iterated over.
+ * @param <B> The resulting type being iterated over.
*
* @param itrA
* The iterator for input values.
@@ -114,4 +73,43 @@ public class IteratorUtils {
Function<A, Iterator<B>> itrB) {
return new ChainIterator<>(itrA, itrB);
}
+
+ /**
+ * Perform a left-fold over an iterator.
+ *
+ * @param <ElementType> The type of elements in the iterator.
+ * @param <ResultType> The result from the fold.
+ *
+ * @param itr The items to iterate over.
+ * @param zero The initial element for the fold.
+ * @param folder The function that does the folding.
+ *
+ * @return The result of folding over the iterator.
+ */
+ public static <ElementType, ResultType> ResultType foldLeft(
+ Iterable<ElementType> itr,
+ ResultType zero,
+ BiFunction<ElementType, ResultType, ResultType> folder)
+ {
+ ResultType state = zero;
+ for (ElementType elem : itr) {
+ state = folder.apply(elem, state);
+ }
+ return state;
+ }
+
+ /**
+ * Creates an 'entangled' pair of a consumer and an iterator.
+ *
+ * @param <ElementType> The type of value involved.
+ *
+ * @return A pair consisting of a consumer of values, and an iterator that
+ * yields the consumed values.
+ */
+ public static <ElementType>
+ IPair<Consumer<ElementType>, Iterator<ElementType>> entangle()
+ {
+ Queue<ElementType> backer = new ArrayDeque<>();
+ return IPair.pair(backer::add, new QueueBackedIterator<>(backer));
+ }
}
diff --git a/base/src/main/java/bjc/utils/funcutils/QueueBackedIterator.java b/base/src/main/java/bjc/utils/funcutils/QueueBackedIterator.java
new file mode 100644
index 0000000..8b9f401
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcutils/QueueBackedIterator.java
@@ -0,0 +1,36 @@
+package bjc.utils.funcutils;
+
+import java.util.*;
+
+/**
+ * An iterator backed by a queue.
+ *
+ * @author Ben Culkin
+ *
+ * @param <ElementType> The type of element
+ */
+public class QueueBackedIterator<ElementType>
+ implements Iterator<ElementType>
+{
+ private final Queue<ElementType> backer;
+
+ /**
+ * Create a new queue-backed iterator.
+ *
+ * @param backer The queue which backs this iterator.
+ */
+ public QueueBackedIterator(Queue<ElementType> backer)
+ {
+ this.backer = backer;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !backer.isEmpty();
+ }
+
+ @Override
+ public ElementType next() {
+ return backer.remove();
+ }
+} \ No newline at end of file
diff --git a/base/src/main/java/bjc/utils/funcutils/Strategy.java b/base/src/main/java/bjc/utils/funcutils/Strategy.java
new file mode 100644
index 0000000..316879f
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcutils/Strategy.java
@@ -0,0 +1,81 @@
+package bjc.utils.funcutils;
+
+import java.util.concurrent.*;
+import java.util.function.*;
+
+/**
+ * Strategy for dealing with parallel execution.
+ *
+ * @author Ben Culkin
+ *
+ * @param <Output> The type returned by the tasks.
+ *
+ */
+public interface Strategy<Output> extends Function<Callable<Output>, Future<Output>>
+{
+ /**
+ * Convert a function into one which operates concurrently, using this strategy.
+ *
+ * @param <Input> The type of the function argument.
+ *
+ * @param func The type of the function.
+ *
+ * @return A function which executes concurrently.
+ */
+ public default <Input> Function<Input, Future<Output>> using(Function<Input, Output> func)
+ {
+ return (input) -> this.apply(() -> func.apply(input));
+ }
+
+ /**
+ * A strategy which will run tasks in serial.
+ *
+ * @param <Output> The type returned by the task.
+ *
+ * @return A strategy which executes things serially.
+ */
+ public static <Output> Strategy<Output> serial()
+ {
+ return (call) -> {
+ FutureTask<Output> task = new FutureTask<>(call);
+ task.run();
+ return task;
+ };
+ }
+ /**
+ * A strategy which creates a fresh thread to execute a task on.
+ *
+ * @param <Output> The type returned by the task.
+ *
+ * @return A strategy which uses threads to create tasks.
+ */
+ public static <Output> Strategy<Output> simpleThread()
+ {
+ // I leave this as an example as of what is possible with combinators.
+ // return (call) -> invoke(introducing(
+ // () -> new FutureTask<>(call),
+ // (task, input) -> doWith(
+ // (FutureTask<Output> tsk) ->
+ // new Thread(task).start()).apply(task)
+ // ));
+ return (call) -> {
+ FutureTask<Output> task = new FutureTask<>(call);
+ new Thread(task).start();
+ return task;
+ };
+ }
+
+ /**
+ * A strategy that uses an executor service.
+ *
+ * @param <Output> The type returned by the task.
+ *
+ * @param svc The executor service to use.
+ *
+ * @return A strategy which uses the provided executor.
+ */
+ public static <Output> Strategy<Output> executorService(ExecutorService svc)
+ {
+ return svc::submit;
+ }
+}