diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-11 21:54:44 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-11 21:54:44 -0400 |
| commit | c8a00b789671d59589bcb5520c1e9d208bcc27f6 (patch) | |
| tree | 6b64e3c78f56d025c78ab08a9edc038af0b6e821 /BJC-Utils2/src/main/java | |
| parent | a716a7a53f85a6901128896da508d31c172011b4 (diff) | |
Work on restructing data.
Diffstat (limited to 'BJC-Utils2/src/main/java')
12 files changed, 762 insertions, 129 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java index a20ff36..98f425f 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java @@ -2,7 +2,6 @@ package bjc.utils.data; import java.util.function.BiConsumer; import java.util.function.BiFunction; -import java.util.function.Function; /** * An interface representing a pair of values @@ -14,26 +13,7 @@ import java.util.function.Function; * @param <R> * The type stored in the right side of the pair */ -public interface IPair<L, R> { - - /** - * Create a new pair by applying the given functions to the left/right. - * Does not change the internal contents of this pair. - * - * @param <L2> - * The new left type of the pair - * @param <R2> - * The new right type of the pair - * - * @param leftTransformer - * The function to apply to the left value. - * @param rightTransformer - * The function to apply to the right value. - * @return A new pair containing the two modified values. - */ - public <L2, R2> IPair<L2, R2> apply(Function<L, L2> leftTransformer, - Function<R, R2> rightTransformer); - +public interface IPair<L, R> { /** * Apply a function to the two internal values that returns a new pair. * @@ -47,8 +27,8 @@ public interface IPair<L, R> { * 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); + 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 diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java index 03f2eed..87727be 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java @@ -2,7 +2,6 @@ package bjc.utils.data; import java.util.function.BiConsumer; import java.util.function.BiFunction; -import java.util.function.Function; /** * Holds a pair of values of two different types. @@ -50,24 +49,6 @@ public class Pair<L, R> implements IPair<L, R> { /* * (non-Javadoc) * - * @see bjc.utils.data.IPair#apply(java.util.function.Function, - * java.util.function.Function) - */ - @Override - public <L2, R2> IPair<L2, R2> apply(Function<L, L2> leftTransformer, - Function<R, R2> rightTransformer) { - if (leftTransformer == null || rightTransformer == null) { - throw new NullPointerException( - "Transformers must be non-null"); - } - - return new Pair<>(leftTransformer.apply(leftValue), - rightTransformer.apply(rightValue)); - } - - /* - * (non-Javadoc) - * * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer) */ @Override @@ -110,7 +91,7 @@ public class Pair<L, R> implements IPair<L, R> { } else { rightValueString = "(null)"; } - + return "pair[l=" + leftValueString + ", r=" + rightValueString + "]"; } 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 2767897..7d1d7a0 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 @@ -15,8 +15,11 @@ import java.util.function.UnaryOperator; public interface IHolder<ContainedType> { /** * Bind a function across the value in this container - * @param <BoundType> The type of value in this container - * @param binder The function to bind to the value + * + * @param <BoundType> + * The type of value in this container + * @param binder + * The function to bind to the value * @return A holder from binding the value */ public <BoundType> IHolder<BoundType> bind( @@ -82,4 +85,15 @@ public interface IHolder<ContainedType> { */ public <UnwrappedType> UnwrappedType unwrap( Function<ContainedType, UnwrappedType> unwrapper); + + /** + * Replace the held value with a new one + * + * @param newValue + * The value to hold instead + * @return The holder itself + */ + public default IHolder<ContainedType> replace(ContainedType newValue) { + return transform((oldValue) -> 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 new file mode 100644 index 0000000..fb9648e --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java @@ -0,0 +1,84 @@ +package bjc.utils.data.experimental; + +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Represents a pair of values + * + * @author ben + * @param <LeftType> + * The type of the left side of the pair + * @param <RightType> + * The type of the right side of the pair + * + */ +public interface IPair<LeftType, RightType> { + /** + * Bind a function to the left value in this pair + * + * @param <BoundLeft> + * The type of the bound value + * @param leftBinder + * The function to use to bind + * @return A pair with the left type bound + */ + public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( + Function<LeftType, IPair<BoundLeft, RightType>> leftBinder); + + /** + * Bind a function to the right value in this pair + * + * @param <BoundRight> + * The type of the bound value + * @param rightBinder + * The function to use to bind + * @return A pair with the right type bound + */ + public <BoundRight> IPair<LeftType, BoundRight> bindRight( + Function<RightType, IPair<LeftType, BoundRight>> rightBinder); + + /** + * Bind a function across the values in this pair + * + * @param <BoundLeft> + * The type of the bound left + * @param <BoundRight> + * The type of the bound right + * @param binder + * The function to bind with + * @return The bound pair + */ + public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( + BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder); + + /** + * Merge the two values in this pair into a single value + * + * @param <MergedType> + * The type of the single value + * @param merger + * The function to use for merging + * @return The pair, merged into a single value + */ + public <MergedType> MergedType merge( + BiFunction<LeftType, RightType, MergedType> merger); + + /** + * Get the value on the left side of the pair + * + * @return The value on the left side of the pair + */ + public default LeftType getLeft() { + return merge((leftValue, rightValue) -> leftValue); + } + + /** + * Get the value on the right side of the pair + * + * @return The value on the right side of the pair + */ + public default RightType getRight() { + return merge((leftValue, rightValue) -> rightValue); + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java index 3cf0987..1780f2d 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Identity.java @@ -42,29 +42,32 @@ public class Identity<ContainedType> implements IHolder<ContainedType> { return binder.apply(heldValue); } + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ @Override - public <MappedType> IHolder<MappedType> map( - Function<ContainedType, MappedType> mapper) { - return new Identity<>(mapper.apply(heldValue)); - } - - @Override - public IHolder<ContainedType> transform( - UnaryOperator<ContainedType> transformer) { - heldValue = transformer.apply(heldValue); + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } - return this; - } + Identity<?> other = (Identity<?>) obj; - @Override - public <UnwrappedType> UnwrappedType unwrap( - Function<ContainedType, UnwrappedType> unwrapper) { - return unwrapper.apply(heldValue); - } + if (heldValue == null) { + if (other.heldValue != null) { + return false; + } + } else if (!heldValue.equals(other.heldValue)) { + return false; + } - @Override - public String toString() { - return "holding[v=" + heldValue + "]"; + return true; } /* @@ -85,31 +88,28 @@ public class Identity<ContainedType> implements IHolder<ContainedType> { return result; } - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj == null) { - return false; - } else if (getClass() != obj.getClass()) { - return false; - } + public <MappedType> IHolder<MappedType> map( + Function<ContainedType, MappedType> mapper) { + return new Identity<>(mapper.apply(heldValue)); + } - Identity<?> other = (Identity<?>) obj; + @Override + public String toString() { + return "holding[v=" + heldValue + "]"; + } - if (heldValue == null) { - if (other.heldValue != null) { - return false; - } - } else if (!heldValue.equals(other.heldValue)) { - return false; - } + @Override + public IHolder<ContainedType> transform( + UnaryOperator<ContainedType> transformer) { + heldValue = transformer.apply(heldValue); - return true; + return this; + } + + @Override + public <UnwrappedType> UnwrappedType unwrap( + Function<ContainedType, UnwrappedType> unwrapper) { + return unwrapper.apply(heldValue); } }
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java index e919fec..0d6fcef 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Lazy.java @@ -26,8 +26,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { private boolean holderBound; - private IFunctionalList<UnaryOperator<BoundContainedType>> actions = - new FunctionalList<>(); + private IFunctionalList<UnaryOperator<BoundContainedType>> actions = new FunctionalList<>(); public BoundLazy(Supplier<IHolder<OldType>> supp, Function<OldType, IHolder<BoundContainedType>> binder) { @@ -38,8 +37,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { @Override public <BoundType> IHolder<BoundType> bind( Function<BoundContainedType, IHolder<BoundType>> bindr) { - IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions = - new FunctionalList<>(); + IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>(); actions.forEach(pendingActions::add); @@ -62,8 +60,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { @Override public <MappedType> IHolder<MappedType> map( Function<BoundContainedType, MappedType> mapper) { - IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions = - new FunctionalList<>(); + IFunctionalList<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>(); actions.forEach(pendingActions::add); @@ -101,12 +98,19 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { return boundHolder.unwrap(unwrapper); } + @Override + public String toString() { + if (holderBound) { + return boundHolder.toString(); + } + + return "(unmaterialized)"; + } } private Supplier<ContainedType> valueSupplier; - private IFunctionalList<UnaryOperator<ContainedType>> actions = - new FunctionalList<>(); + private IFunctionalList<UnaryOperator<ContainedType>> actions = new FunctionalList<>(); private boolean valueMaterialized; @@ -146,8 +150,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { @Override public <BoundType> IHolder<BoundType> bind( Function<ContainedType, IHolder<BoundType>> binder) { - IFunctionalList<UnaryOperator<ContainedType>> pendingActions = - new FunctionalList<>(); + IFunctionalList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); actions.forEach(pendingActions::add); @@ -167,8 +170,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { @Override public <MappedType> IHolder<MappedType> map( Function<ContainedType, MappedType> mapper) { - IFunctionalList<UnaryOperator<ContainedType>> pendingActions = - new FunctionalList<>(); + IFunctionalList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); actions.forEach(pendingActions::add); @@ -210,4 +212,17 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { return unwrapper.apply(heldValue); } + + @Override + public String toString() { + if (valueMaterialized) { + if (actions.isEmpty()) { + return "value[v='" + heldValue + "']"; + } + + return "value[v='" + heldValue + "'] (has pending transforms)"; + } + + return "(unmaterialized)"; + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java new file mode 100644 index 0000000..04a4b61 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/LazyPair.java @@ -0,0 +1,317 @@ +package bjc.utils.data.experimental; + +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * A lazy implementation of a pair + * + * @author ben + * + * @param <LeftType> + * The type on the left side of the pair + * @param <RightType> + * The type on the right side of the pair + */ +public class LazyPair<LeftType, RightType> + implements IPair<LeftType, RightType> { + private static class HalfBoundLazyPair<OldType, NewLeft, NewRight> + implements IPair<NewLeft, NewRight> { + private Supplier<OldType> oldSupplier; + + private Function<OldType, IPair<NewLeft, NewRight>> binder; + + private IPair<NewLeft, NewRight> boundPair; + private boolean pairBound; + + public HalfBoundLazyPair(Supplier<OldType> oldSupp, + Function<OldType, IPair<NewLeft, NewRight>> bindr) { + oldSupplier = oldSupp; + binder = bindr; + } + + @Override + public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft( + Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) { + Supplier<NewLeft> leftSupp = () -> { + IPair<NewLeft, NewRight> newPair = boundPair; + + if (!pairBound) { + newPair = binder.apply(oldSupplier.get()); + } + + return newPair.getLeft(); + }; + + return new HalfBoundLazyPair<>(leftSupp, leftBinder); + } + + @Override + public <BoundRight> IPair<NewLeft, BoundRight> bindRight( + Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) { + Supplier<NewRight> rightSupp = () -> { + IPair<NewLeft, NewRight> newPair = boundPair; + + if (!pairBound) { + newPair = binder.apply(oldSupplier.get()); + } + + return newPair.getRight(); + }; + + return new HalfBoundLazyPair<>(rightSupp, rightBinder); + } + + @Override + public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( + BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) { + IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>( + boundPair); + IHolder<Boolean> newPairMade = new Identity<>(pairBound); + + Supplier<NewLeft> leftSupp = () -> { + if (!newPairMade.getValue()) { + newPair.replace(binder.apply(oldSupplier.get())); + newPairMade.replace(true); + } + + return newPair.unwrap((pair) -> pair.getLeft()); + }; + + Supplier<NewRight> rightSupp = () -> { + if (!newPairMade.getValue()) { + newPair.replace(binder.apply(oldSupplier.get())); + newPairMade.replace(true); + } + + return newPair.unwrap((pair) -> pair.getRight()); + }; + + return new BoundLazyPair<>(leftSupp, rightSupp, bindr); + } + + @Override + public <MergedType> MergedType merge( + BiFunction<NewLeft, NewRight, MergedType> merger) { + if (!pairBound) { + boundPair = binder.apply(oldSupplier.get()); + + pairBound = true; + } + + return boundPair.merge(merger); + } + } + + private static class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> + implements IPair<NewLeft, NewRight> { + private Supplier<OldLeft> leftSupplier; + private Supplier<OldRight> rightSupplier; + + private BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> binder; + + private IPair<NewLeft, NewRight> boundPair; + + private boolean pairBound; + + public BoundLazyPair(Supplier<OldLeft> leftSupp, + Supplier<OldRight> rightSupp, + BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> bindr) { + leftSupplier = leftSupp; + rightSupplier = rightSupp; + binder = bindr; + } + + @Override + public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft( + Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) { + Supplier<NewLeft> leftSupp = () -> { + IPair<NewLeft, NewRight> newPair = boundPair; + + if (!pairBound) { + newPair = binder.apply(leftSupplier.get(), + rightSupplier.get()); + } + + return newPair.getLeft(); + }; + + return new HalfBoundLazyPair<>(leftSupp, leftBinder); + } + + @Override + public <BoundRight> IPair<NewLeft, BoundRight> bindRight( + Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) { + Supplier<NewRight> rightSupp = () -> { + IPair<NewLeft, NewRight> newPair = boundPair; + + if (!pairBound) { + newPair = binder.apply(leftSupplier.get(), + rightSupplier.get()); + } + + return newPair.getRight(); + }; + + return new HalfBoundLazyPair<>(rightSupp, rightBinder); + } + + @Override + public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( + BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) { + IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>( + boundPair); + IHolder<Boolean> newPairMade = new Identity<>(pairBound); + + return new BoundLazyPair<>(() -> { + if (!newPairMade.getValue()) { + newPair.replace(binder.apply(leftSupplier.get(), + rightSupplier.get())); + + newPairMade.replace(false); + } + + return newPair.unwrap((pair) -> pair.getLeft()); + }, () -> { + if (!newPairMade.getValue()) { + newPair.replace(binder.apply(leftSupplier.get(), + rightSupplier.get())); + + newPairMade.replace(false); + } + + return newPair.unwrap((pair) -> pair.getRight()); + }, bindr); + } + + @Override + public <MergedType> MergedType merge( + BiFunction<NewLeft, NewRight, MergedType> merger) { + if (!pairBound) { + boundPair = binder.apply(leftSupplier.get(), + rightSupplier.get()); + + pairBound = true; + } + + return boundPair.merge(merger); + } + } + + private LeftType leftValue; + private RightType rightValue; + + private Supplier<LeftType> leftSupplier; + private Supplier<RightType> rightSupplier; + + private boolean leftMaterialized; + private boolean rightMaterialized; + + /** + * Create a new lazy pair, using the set value s + * + * @param leftVal + * The value for the left side of the pair + * @param rightVal + * The value for the right side of the pair + */ + public LazyPair(LeftType leftVal, RightType rightVal) { + leftValue = leftVal; + rightValue = rightVal; + + leftMaterialized = true; + rightMaterialized = true; + } + + /** + * Create a new lazy pair from the given value sources + * + * @param leftSupp + * The source for a value on the left side of the pair + * @param rightSupp + * The source for a value on the right side of the pair + */ + public LazyPair(Supplier<LeftType> leftSupp, + Supplier<RightType> rightSupp) { + leftSupplier = leftSupp; + rightSupplier = rightSupp; + + leftMaterialized = false; + rightMaterialized = false; + } + + @Override + public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( + Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { + Supplier<LeftType> leftSupp = () -> { + if (leftMaterialized) { + return leftValue; + } + + return leftSupplier.get(); + }; + + return new HalfBoundLazyPair<>(leftSupp, leftBinder); + } + + @Override + public <BoundRight> IPair<LeftType, BoundRight> bindRight( + Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { + Supplier<RightType> rightSupp = () -> { + if (rightMaterialized) { + return rightValue; + } + + return rightSupplier.get(); + }; + + return new HalfBoundLazyPair<>(rightSupp, rightBinder); + } + + @Override + public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( + BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { + return new BoundLazyPair<>(leftSupplier, rightSupplier, binder); + } + + @Override + public <MergedType> MergedType merge( + BiFunction<LeftType, RightType, MergedType> merger) { + if (!leftMaterialized) { + leftValue = leftSupplier.get(); + + leftMaterialized = true; + } + + if (!rightMaterialized) { + rightValue = rightSupplier.get(); + + rightMaterialized = true; + } + + return merger.apply(leftValue, rightValue); + } + + @Override + public LeftType getLeft() { + if (!leftMaterialized) { + leftValue = leftSupplier.get(); + + leftMaterialized = true; + } + + return leftValue; + } + + @Override + public RightType getRight() { + if (!rightMaterialized) { + rightValue = rightSupplier.get(); + + rightMaterialized = true; + } + + return rightValue; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java new file mode 100644 index 0000000..87378d7 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/Pair.java @@ -0,0 +1,63 @@ +package bjc.utils.data.experimental; + +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * A pair of values, with nothing special about them. + * + * @author ben + * + * @param <LeftType> + * The type of the left value + * @param <RightType> + * The type of the right value + */ +public class Pair<LeftType, RightType> + implements IPair<LeftType, RightType> { + private LeftType leftValue; + private RightType rightValue; + + /** + * Create a new pair with both sides set to null + */ + public Pair() { + } + + /** + * Create a new pair with both sides set to the specified values + * + * @param left + * The value of the left side + * @param right + * The value of the right side + */ + public Pair(LeftType left, RightType right) { + leftValue = left; + rightValue = right; + } + + @Override + public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( + Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { + return leftBinder.apply(leftValue); + } + + @Override + public <BoundRight> IPair<LeftType, BoundRight> bindRight( + Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { + return rightBinder.apply(rightValue); + } + + @Override + public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( + BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { + return binder.apply(leftValue, rightValue); + } + + @Override + public <MergedType> MergedType merge( + BiFunction<LeftType, RightType, MergedType> merger) { + return merger.apply(leftValue, rightValue); + } +}
\ No newline at end of file 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 index 85b7493..141d558 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java @@ -171,7 +171,7 @@ public class LazyHolder<T> implements IHolder<T>, ILazy { * The value held in the holder */ public LazyHolder(T value) { - heldValue = value; + heldSource = () -> value; } @Override 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 index 70f5478..dcaeeba 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java @@ -2,7 +2,6 @@ package bjc.utils.data.lazy; import java.util.function.BiConsumer; import java.util.function.BiFunction; -import java.util.function.Function; import java.util.function.Supplier; import bjc.utils.data.IHolder; @@ -88,26 +87,6 @@ public class LazyPair<L, R> implements IPair<L, R>, ILazy { /* * (non-Javadoc) * - * @see bjc.utils.data.IPair#apply(java.util.function.Function, - * java.util.function.Function) - */ - @Override - public <L2, R2> IPair<L2, R2> apply(Function<L, L2> leftTransform, - Function<R, R2> rightTransform) { - if (leftTransform == null || rightTransform == null) { - throw new NullPointerException("Transforms must be non-null"); - } - - IHolder<IPair<L2, R2>> newPair = delegatePair - .map((currentPair) -> currentPair.apply(leftTransform, - rightTransform)); - - return new LazyPair<>(newPair, materialized, true); - } - - /* - * (non-Javadoc) - * * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer) */ @Override 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 new file mode 100644 index 0000000..4bd3832 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java @@ -0,0 +1,202 @@ +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 diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java index 68ec70e..3252351 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java @@ -7,6 +7,7 @@ import java.util.function.Function; import java.util.function.Predicate; import bjc.utils.data.GenHolder; +import bjc.utils.data.IHolder; import bjc.utils.data.IPair; import bjc.utils.data.Pair; import bjc.utils.funcdata.IFunctionalList; @@ -45,8 +46,7 @@ public class TreeConstructor { if (queuedASTs.size() < 2) { throw new IllegalStateException( "Attempted to parse binary operator without enough operands.\n" - + "Problem operator is " - + element + + "Problem operator is " + element + "\nPossible operand is: \n\t" + queuedASTs.peek()); } @@ -63,13 +63,13 @@ public class TreeConstructor { } } - private GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState; + private IHolder<IPair<Deque<AST<T>>, AST<T>>> initialState; private Predicate<T> operatorPredicate; private Predicate<T> isSpecialOperator; private Function<Deque<AST<T>>, AST<T>> handleSpecialOperator; public TokenTransformer( - GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState, + IHolder<IPair<Deque<AST<T>>, AST<T>>> initialState, Predicate<T> operatorPredicate, Predicate<T> isSpecialOperator, Function<Deque<AST<T>>, AST<T>> handleSpecialOperator) { @@ -93,10 +93,8 @@ public class TreeConstructor { }); initialState.transform((pair) -> { - return pair.apply((Deque<AST<T>> queue) -> { - return queue; - }, (AST<T> currentAST) -> { - return newAST; + return pair.bind((queue, currentAST) -> { + return new Pair<>(queue, newAST); }); }); } @@ -160,7 +158,7 @@ public class TreeConstructor { "Special operator determiner must not be null"); } - GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState = new GenHolder<>( + IHolder<IPair<Deque<AST<T>>, AST<T>>> initialState = new GenHolder<>( new Pair<>(new LinkedList<>(), null)); tokens.forEach( |
