diff options
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/data')
10 files changed, 16 insertions, 1031 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java deleted file mode 100644 index bd87f07..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java +++ /dev/null @@ -1,113 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Holds a single value of a specific type. This is used for indirect - * references to data, and more specifically for accessing non-final - * variables from a lambda. AKA the identity monad - * - * This is an eager variant of {@link IHolder} - * - * @author ben - * - * @param <T> - * The type of the data being held - */ -public class GenHolder<T> implements IHolder<T> { - /** - * The state this holder is responsible for. - */ - private T heldValue; - - /** - * Creates a new empty holder, with its state set to null - */ - public GenHolder() { - heldValue = null; - } - - /** - * Creates a new holder, with its state initialized to the provided - * value - * - * @param held - * The state to initialize this holder to. - */ - public GenHolder(T held) { - heldValue = held; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#doWith(java.util.function.Consumer) - */ - @Override - public void doWith(Consumer<T> action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - action.accept(heldValue); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#map(java.util.function.Function) - */ - @Override - public <NewT> IHolder<NewT> map(Function<T, NewT> transformer) { - if (transformer == null) { - throw new NullPointerException("Transformer must be non-null"); - } - - return new GenHolder<>(transformer.apply(heldValue)); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#transform(java.util.function.Function) - */ - @Override - public IHolder<T> transform(Function<T, T> transformer) { - if (transformer == null) { - throw new NullPointerException("Transformer must be non-null"); - } - - heldValue = transformer.apply(heldValue); - - return this; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#unwrap(java.util.function.Function) - */ - @Override - public <E> E unwrap(Function<T, E> unwrapper) { - if (unwrapper == null) { - throw new NullPointerException("Unwrapper must be null"); - } - - return unwrapper.apply(heldValue); - } - - @Override - public String toString() { - if (heldValue == null) { - return "(null)"; - } - - return heldValue.toString(); - } - - @Override - public <E> IHolder<E> bind(Function<T, IHolder<E>> binder) { - return binder.apply(heldValue); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java deleted file mode 100644 index a4f4013..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java +++ /dev/null @@ -1,70 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Generic interface for things that store a single value in a roughly - * monadic fashion - * - * @author ben - * - * @param <T> - * The type of data being stored - */ -public interface IHolder<T> { - - /** - * Call a provided function with the value being held - * - * @param action - * The function to call - */ - public void doWith(Consumer<T> action); - - /** - * Return the result of applying the given transformation to the held - * value. Doesn't change the held value. - * - * @param <NewT> - * The new type of the held value - * - * @param transformer - * The transformation to apply - * @return A holder with the transformed value - */ - public <NewT> IHolder<NewT> map(Function<T, NewT> transformer); - - /** - * Apply the given transformation to the held value. Returns the holder - * for allowing chaining of transforms - * - * @param transformer - * The transform to apply to the value - * @return The holder - */ - public IHolder<T> transform(Function<T, T> transformer); - - /** - * Returns a raw mapped value, not contained in a GenHolder - * - * @param <E> - * The type of the value that is the end result - * - * @param unwrapper - * The function to use for mapping the value - * @return The mapped value outside of a GenHolder - */ - public <E> E unwrap(Function<T, E> unwrapper); - - /** - * Bind the value in this holder to a new value - * - * @param <E> - * The new type of the held value - * @param binder - * The function to do the binding with - * @return The bound value - */ - public <E> IHolder<E> bind(Function<T, IHolder<E>> binder); -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java deleted file mode 100644 index 98f425f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; - -/** - * An interface representing a pair of values - * - * @author ben - * - * @param <L> - * The type stored in the left side of the pair - * @param <R> - * The type stored in the right side of the pair - */ -public interface IPair<L, R> { - /** - * Apply a function to the two internal values that returns a new pair. - * - * Is a monadic bind. - * - * @param <L2> - * The new left pair type - * @param <R2> - * The new right pair type - * @param binder - * The function to use as a bind - * @return The new pair - */ - public <L2, R2> IPair<L2, R2> bind( - BiFunction<L, R, IPair<L2, R2>> binder); - - /** - * Execute an action with the values of this pair. Has no effect on the - * internal contents - * - * @param action - * The action to execute on the values - */ - public void doWith(BiConsumer<L, R> action); - - /** - * Collapse this pair to a single value. Does not change the internal - * contents of this pair. - * - * @param <E> - * The resulting type after merging - * - * @param merger - * The function to use to collapse the pair. - * @return The collapsed value. - */ - public <E> E merge(BiFunction<L, R, E> merger); -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java deleted file mode 100644 index 87727be..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java +++ /dev/null @@ -1,104 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; - -/** - * Holds a pair of values of two different types. - * - * Is an eager variant of {@link IPair} - * - * @author ben - * - * @param <L> - * The type of the thing held on the left (first) - * @param <R> - * The type of the thing held on the right (second) - */ -public class Pair<L, R> implements IPair<L, R> { - /** - * The left value of the pair - */ - protected L leftValue; - - /** - * The right value of the pair - */ - protected R rightValue; - - /** - * Create a new pair that holds two nulls. - */ - public Pair() { - - } - - /** - * Create a new pair holding the specified values. - * - * @param left - * The value to hold on the left. - * @param right - * The value to hold on the right. - */ - public Pair(L left, R right) { - leftValue = left; - rightValue = right; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer) - */ - @Override - public void doWith(BiConsumer<L, R> action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - action.accept(leftValue, rightValue); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#merge(java.util.function.BiFunction) - */ - @Override - public <E> E merge(BiFunction<L, R, E> merger) { - if (merger == null) { - throw new NullPointerException("Merger must be non-null"); - } - - return merger.apply(leftValue, rightValue); - } - - @Override - public String toString() { - String leftValueString; - - if (leftValue != null) { - leftValueString = leftValue.toString(); - } else { - leftValueString = "(null)"; - } - - String rightValueString; - - if (rightValue != null) { - rightValueString = rightValue.toString(); - } else { - rightValueString = "(null)"; - } - - return "pair[l=" + leftValueString + ", r=" + rightValueString - + "]"; - } - - @Override - public <L2, R2> IPair<L2, R2> bind( - BiFunction<L, R, IPair<L2, R2>> binder) { - return binder.apply(leftValue, rightValue); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java index 7d1d7a0..6ccf115 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java @@ -94,6 +94,8 @@ public interface IHolder<ContainedType> { * @return The holder itself */ public default IHolder<ContainedType> replace(ContainedType newValue) { - return transform((oldValue) -> newValue); + return transform((oldValue) -> { + return newValue; + }); } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java index fb9648e..f5ca240 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java @@ -1,5 +1,6 @@ package bjc.utils.data.experimental; +import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; @@ -81,4 +82,16 @@ public interface IPair<LeftType, RightType> { public default RightType getRight() { return merge((leftValue, rightValue) -> rightValue); } + + /** + * Immediately perfom the specified action with the contents of this pair + * @param consumer The action to perform on the pair + */ + public default void doWith(BiConsumer<LeftType, RightType> consumer) { + merge((leftValue, rightValue) -> { + consumer.accept(leftValue, rightValue); + + return null; + }); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java deleted file mode 100644 index a4fab67..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java +++ /dev/null @@ -1,35 +0,0 @@ -package bjc.utils.data.lazy; - -/** - * Interface for some maintenance operations on lazy objects - * - * @author ben - * - */ -public interface ILazy { - /** - * Check if this object has been materialized - * - * @return Whether or not this object has been materialized - */ - public boolean isMaterialized(); - - /** - * Check if there are pending actions that need to be applied - * - * @return Whether or not there are pending actions - */ - public boolean hasPendingActions(); - - /** - * Make this object materialize itelf - */ - public void materialize(); - - /** - * Make this object apply any pending objects - * - * As a requirement, will materialize the object if it is not materialized - */ - public void applyPendingActions(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java deleted file mode 100644 index 141d558..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java +++ /dev/null @@ -1,284 +0,0 @@ -package bjc.utils.data.lazy; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IFunctionalList; - -/** - * Holds a single value of a specific type. This is used for indirect - * references to data, and more specifically for accessing non-final - * variables from a lambda. AKA the identity monad - * - * This is a lazy variant of {@link IHolder} - * - * @author ben - * - * @param <T> - * The type of the data being held - */ -public class LazyHolder<T> implements IHolder<T>, ILazy { - private static final class LazyHolderHolder<T2> - implements IHolder<T2> { - private Supplier<IHolder<T2>> holderSource; - - private IHolder<T2> holder; - - private IFunctionalList<Function<T2, T2>> actions = new FunctionalList<>(); - - public LazyHolderHolder(Supplier<IHolder<T2>> source) { - - holderSource = source; - } - - @Override - public void doWith(Consumer<T2> action) { - actions.add((val) -> { - action.accept(val); - - return val; - }); - } - - @Override - public <NewT> IHolder<NewT> map(Function<T2, NewT> transformer) { - // TODO implement me - throw new UnsupportedOperationException( - "Mapping is not yet supported on bound holders"); - } - - @Override - public IHolder<T2> transform(Function<T2, T2> transformer) { - actions.add(transformer); - - return this; - } - - @Override - public <E> E unwrap(Function<T2, E> unwrapper) { - if (holder == null) { - holder = holderSource.get(); - } - - if (!actions.isEmpty()) { - actions.forEach((transform) -> { - holder.transform(transform); - }); - } - - return holder.unwrap(unwrapper); - } - - @Override - public <E> IHolder<E> bind(Function<T2, IHolder<E>> binder) { - return new LazyHolderHolder<>(() -> { - return binder.apply(unwrap((val) -> val)); - }); - } - - @Override - public String toString() { - if (holderSource == null) { - if (holder == null) { - return "(null)"; - } - - return holder.toString(); - } - - if (holder == null) { - return "(unmaterialized values)"; - } - - return holder.toString(); - } - } - - private static final class LazyHolderSupplier<NewT, T2> - implements Supplier<NewT> { - private IFunctionalList<Function<T2, T2>> pendingActions; - private Function<T2, NewT> pendingTransform; - - private T2 heldValue; - private Supplier<T2> heldSource; - - public LazyHolderSupplier(IFunctionalList<Function<T2, T2>> actons, - Function<T2, NewT> transform, T2 heldValue, - Supplier<T2> heldSource) { - // Resolve latent bug I just realized. After a map, adding new - // actions to the original holder could've resulted in changes - // to all unactualized mapped values from that holder - pendingActions = new FunctionalList<>(); - - for (Function<T2, T2> action : actons.toIterable()) { - pendingActions.add(action); - } - - this.pendingTransform = transform; - this.heldValue = heldValue; - this.heldSource = heldSource; - } - - @Override - public NewT get() { - if (heldValue == null) { - return pendingActions.reduceAux(heldSource.get(), - Function<T2, T2>::apply, pendingTransform::apply); - } - - return pendingActions.reduceAux(heldValue, - Function<T2, T2>::apply, pendingTransform::apply); - } - } - - /** - * List of queued actions to be performed on realized values - */ - private IFunctionalList<Function<T, T>> actions = new FunctionalList<>(); - - /** - * The value internally held by this lazy holder - */ - private T heldValue; - - /** - * The source for a value held by this lazy holder - */ - private Supplier<T> heldSource; - - /** - * Create a new lazy holder with the given supplier - * - * @param source - * The supplier for a value when it is neededs - */ - public LazyHolder(Supplier<T> source) { - if (source == null) { - throw new NullPointerException("Source must be non-null"); - } - - heldSource = source; - heldValue = null; - } - - /** - * Create a new lazy holder with the given value - * - * @param value - * The value held in the holder - */ - public LazyHolder(T value) { - heldSource = () -> value; - } - - @Override - public void doWith(Consumer<T> action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - transform((value) -> { - // Do the action with the value - action.accept(value); - - // Return the untransformed value - return value; - }); - } - - @Override - public <NewT> IHolder<NewT> map(Function<T, NewT> transform) { - if (transform == null) { - throw new NullPointerException("Transform must be non-null"); - } - - // Don't actually map until we need to - return new LazyHolder<>(new LazyHolderSupplier<>(actions, - transform, heldValue, heldSource)); - } - - @Override - public IHolder<T> transform(Function<T, T> transform) { - if (transform == null) { - throw new NullPointerException("Transform must be non-null"); - } - - // Queue the transform until we need to apply it - actions.add(transform); - - return this; - } - - @Override - public <E> E unwrap(Function<T, E> unwrapper) { - if (unwrapper == null) { - throw new NullPointerException("Unwrapper must be null"); - } - - // Actualize ourselves - if (heldValue == null) { - heldValue = heldSource.get(); - } - - // Apply all pending transforms - actions.forEach((action) -> heldValue = action.apply(heldValue)); - - return unwrapper.apply(heldValue); - } - - @Override - public boolean isMaterialized() { - if (heldSource != null) { - // We're materialized if a value exists - return heldValue == null; - } - - // We're materialized by default - return true; - } - - @Override - public boolean hasPendingActions() { - return actions.isEmpty(); - } - - @Override - public void materialize() { - // Only materialize if we haven't already - if (!isMaterialized()) { - heldValue = heldSource.get(); - } - } - - @Override - public void applyPendingActions() { - materialize(); - - actions.forEach((action) -> { - heldValue = action.apply(heldValue); - }); - } - - @Override - public <T2> IHolder<T2> bind(Function<T, IHolder<T2>> binder) { - return new LazyHolderHolder<>(() -> { - return binder.apply(unwrap((val) -> val)); - }); - } - - @Override - public String toString() { - if (isMaterialized()) { - if (hasPendingActions()) { - return heldValue.toString() + " (has pending actions)"; - } - - return heldValue.toString(); - } - - return "(unmaterialized value)"; - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java deleted file mode 100644 index dcaeeba..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java +++ /dev/null @@ -1,168 +0,0 @@ -package bjc.utils.data.lazy; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; - -/** - * A lazy holder of two values - * - * Lazy variant of {@link IPair} - * - * @author ben - * - * @param <L> - * The type of value stored on the left side of the pair - * @param <R> - * The type of value stored on the right side of the pair - */ -public class LazyPair<L, R> implements IPair<L, R>, ILazy { - /** - * The backing store for this pair - */ - protected IHolder<IPair<L, R>> delegatePair; - - private boolean materialized = false; - private boolean pendingActions = false; - - /** - * Create a new blank lazy pair - */ - public LazyPair() { - delegatePair = new LazyHolder<>(new Pair<>()); - } - - /** - * Create a new lazy pair with the specified initial values - * - * @param leftValue - * The initial value for the left side of the pair - * @param rightValue - * The initial value for the right side of the pair - */ - public LazyPair(L leftValue, R rightValue) { - materialized = true; - - delegatePair = new LazyHolder<>(new Pair<>(leftValue, rightValue)); - } - - /** - * Create a new lazy pair with the specified sources for initial values - * - * @param leftValueSource - * The function to call for the left initial value - * @param rightValueSource - * The function to call for the right initial value - */ - public LazyPair(Supplier<L> leftValueSource, - Supplier<R> rightValueSource) { - if (leftValueSource == null || rightValueSource == null) { - throw new NullPointerException("Sources must be non-null"); - } - - delegatePair = new LazyHolder<>(() -> { - return new Pair<>(leftValueSource.get(), - rightValueSource.get()); - }); - } - - /** - * Create a new lazy pair with a specified internal delegate - * - * @param delegate - * The internal delegate for the pair - */ - private LazyPair(IHolder<IPair<L, R>> delegate, boolean mater, - boolean pend) { - materialized = mater; - pendingActions = pend; - - delegatePair = delegate; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer) - */ - @Override - public void doWith(BiConsumer<L, R> action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - pendingActions = true; - - delegatePair.doWith((currentPair) -> { - currentPair.doWith(action); - }); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#merge(java.util.function.BiFunction) - */ - @Override - public <E> E merge(BiFunction<L, R, E> merger) { - if (merger == null) { - throw new NullPointerException("Merger must be non-null"); - } - - materialized = true; - pendingActions = false; - - return delegatePair - .unwrap((currentPair) -> currentPair.merge(merger)); - } - - @Override - public boolean isMaterialized() { - return materialized; - } - - @Override - public boolean hasPendingActions() { - return pendingActions; - } - - /* - * Note: Materializing will also apply all currently pending actions - */ - @Override - public void materialize() { - merge((left, right) -> null); - - materialized = true; - pendingActions = false; - } - - @Override - public void applyPendingActions() { - merge((left, right) -> null); - - materialized = true; - pendingActions = false; - } - - @Override - public <L2, R2> IPair<L2, R2> bind( - BiFunction<L, R, IPair<L2, R2>> binder) { - IHolder<IPair<L2, R2>> newDelegate = delegatePair - .map((pairVal) -> { - return pairVal.bind(binder); - }); - - return new LazyPair<>(newDelegate, isMaterialized(), - hasPendingActions()); - } - - @Override - public String toString() { - return delegatePair.toString(); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java deleted file mode 100644 index 4bd3832..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java +++ /dev/null @@ -1,202 +0,0 @@ -package bjc.utils.data.lazy; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -import bjc.utils.data.GenHolder; -import bjc.utils.data.IPair; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IFunctionalList; - -/** - * New implementation of lazy pair not delegating to {@link LazyHolder} - * - * @author ben - * @param <L> - * The type on the left side of the pair - * @param <R> - * The type on the right side of the pair - * - */ -public class NewLazyPair<L, R> implements IPair<L, R>, ILazy { - private static class BoundLazyPair<OldL, OldR, NewL, NewR> - implements IPair<NewL, NewR> { - private Supplier<OldL> oldLeftSupplier; - private Supplier<OldR> oldRightSupplier; - - private BiFunction<OldL, OldR, IPair<NewL, NewR>> newPairSupplier; - - private IPair<NewL, NewR> newPair; - - private boolean newPairMaterialized; - - public BoundLazyPair(Supplier<OldL> leftSup, - Supplier<OldR> rightSup, - BiFunction<OldL, OldR, IPair<NewL, NewR>> binder) { - oldLeftSupplier = leftSup; - oldRightSupplier = rightSup; - - newPairSupplier = binder; - } - - @Override - public <L2, R2> IPair<L2, R2> bind( - BiFunction<NewL, NewR, IPair<L2, R2>> binder) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void doWith(BiConsumer<NewL, NewR> action) { - // TODO Auto-generated method stub - - } - - @Override - public <E> E merge(BiFunction<NewL, NewR, E> merger) { - if (!newPairMaterialized) { - newPair = newPairSupplier.apply(oldLeftSupplier.get(), - oldRightSupplier.get()); - } - - return newPair.merge(merger); - } - } - - private L leftValue; - private R rightValue; - - private Supplier<R> rightValueSupplier; - private Supplier<L> leftValueSupplier; - - private boolean rightMaterialized; - private boolean leftMaterialized; - - private IFunctionalList<BiConsumer<L, R>> actions; - - /** - * Create a new lazy pair - * - * @param leftVal - * The left value in the pair - * @param rightVal - * The right value in the pair - */ - public NewLazyPair(L leftVal, R rightVal) { - leftValueSupplier = () -> leftVal; - rightValueSupplier = () -> rightVal; - } - - /** - * Create a new lazy pair - * - * @param leftSupplier - * The supplier for the left value in the pair - * @param rightSupplier - * The supplier for the right value in the pair - */ - public NewLazyPair(Supplier<L> leftSupplier, - Supplier<R> rightSupplier) { - leftValueSupplier = leftSupplier; - rightValueSupplier = rightSupplier; - } - - @Override - public void applyPendingActions() { - if (!isMaterialized()) { - throw new UnsupportedOperationException( - "Can only apply actions to materialized values"); - } - - actions.forEach((action) -> { - action.accept(leftValue, rightValue); - }); - - actions = new FunctionalList<>(); - } - - private void applyPossiblyPendingActions(GenHolder<Boolean> hasActions, - IFunctionalList<BiConsumer<L, R>> pendingActions) { - if (hasActions.unwrap((val) -> val) == true) { - pendingActions.forEach((action) -> { - action.accept(leftValue, rightValue); - }); - - hasActions.transform((val) -> false); - } - } - - @Override - public <L2, R2> IPair<L2, R2> bind( - BiFunction<L, R, IPair<L2, R2>> binder) { - GenHolder<Boolean> hasActions = new GenHolder<>(true); - IFunctionalList<BiConsumer<L, R>> pendingActions = new FunctionalList<>(); - - actions.forEach(pendingActions::add); - - return new BoundLazyPair<>(() -> { - applyPossiblyPendingActions(hasActions, pendingActions); - - return leftValue; - }, () -> { - applyPossiblyPendingActions(hasActions, pendingActions); - - return rightValue; - }, binder); - } - - @Override - public void doWith(BiConsumer<L, R> action) { - actions.add(action); - } - - @Override - public boolean hasPendingActions() { - return !actions.isEmpty(); - } - - @Override - public boolean isMaterialized() { - if (leftValueSupplier == null) { - if (rightValueSupplier == null) { - return true; - } - - return rightMaterialized; - } - - if (rightValueSupplier == null) { - return leftMaterialized; - } - - return leftMaterialized && rightMaterialized; - } - - @Override - public void materialize() { - if (isMaterialized()) { - throw new UnsupportedOperationException( - "Cannot materialize lazy object twice"); - } - - if (leftValueSupplier != null) { - leftValue = leftValueSupplier.get(); - } - - if (rightValueSupplier != null) { - rightValue = rightValueSupplier.get(); - } - } - - @Override - public <E> E merge(BiFunction<L, R, E> merger) { - if (!isMaterialized()) { - materialize(); - } - - applyPendingActions(); - - return merger.apply(leftValue, rightValue); - } -}
\ No newline at end of file |
