diff options
| author | Ben Culkin <scorpress@gmail.com> | 2020-12-03 19:21:38 -0500 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2020-12-03 19:21:38 -0500 |
| commit | 0a8f34c27c6ef93c5c94d17728af62c7607e225f (patch) | |
| tree | 3bbbbb6d62649c7411e7ae3d53a75786255ed84e /src/main/java/bjc/data | |
| parent | 097a33bc2ecaa64a664550ddd62ccd8de47c51d0 (diff) | |
Rename types to match Java style
This renames several interfaces that had names like IWhatever, since
that isn't a style that Java uses
Diffstat (limited to 'src/main/java/bjc/data')
22 files changed, 1223 insertions, 1223 deletions
diff --git a/src/main/java/bjc/data/IContext.java b/src/main/java/bjc/data/Context.java index e519501..7efdc4d 100644 --- a/src/main/java/bjc/data/IContext.java +++ b/src/main/java/bjc/data/Context.java @@ -5,7 +5,7 @@ package bjc.data; * @author Ben Culkin * */ -public interface IContext { +public interface Context { /** * Register an object with this context. * @@ -19,7 +19,7 @@ public interface IContext { * * @return The parent of this context. */ - IContext getParent(); + Context getParent(); /** * Get an object from this context. diff --git a/src/main/java/bjc/data/Contexts.java b/src/main/java/bjc/data/Contexts.java index 75c8480..b028ad1 100644 --- a/src/main/java/bjc/data/Contexts.java +++ b/src/main/java/bjc/data/Contexts.java @@ -12,7 +12,7 @@ public class Contexts { /** * The null context, which always throws an exception. */ - public static final IContext NULL = new NullContextImpl(); + public static final Context NULL = new NullContextImpl(); private Contexts() { throw new UnsupportedOperationException(); @@ -23,7 +23,7 @@ public class Contexts { * * @return A context with no parent. */ - public static IContext create() { + public static Context create() { return new ContextImpl(NULL); } @@ -34,13 +34,13 @@ public class Contexts { * * @return A context with the given context as its parent. */ - public static IContext create(IContext parent) { + public static Context create(Context parent) { return new ContextImpl(parent); } - private static class NullContextImpl implements IContext { + private static class NullContextImpl implements Context { @Override - public IContext getParent() { + public Context getParent() { return this; } @@ -60,13 +60,13 @@ public class Contexts { } } - private static class ContextImpl implements IContext { + private static class ContextImpl implements Context { - private final IContext parent; + private final Context parent; private final Map<String, Object> objects; - public ContextImpl(IContext parent) { + public ContextImpl(Context parent) { this.parent = parent; this.objects = new HashMap<>(); } @@ -96,7 +96,7 @@ public class Contexts { } @Override - public IContext getParent() { + public Context getParent() { return parent; } } diff --git a/src/main/java/bjc/data/Either.java b/src/main/java/bjc/data/Either.java index 0ac3181..e4bc63d 100644 --- a/src/main/java/bjc/data/Either.java +++ b/src/main/java/bjc/data/Either.java @@ -15,7 +15,7 @@ import java.util.function.Function; * The type that could be on the right. * */ -public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { +public class Either<LeftType, RightType> implements Pair<LeftType, RightType> { /** * Create a new either with the left value occupied. * @@ -73,16 +73,16 @@ public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { } @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { + public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> bind( + final BiFunction<LeftType, RightType, Pair<BoundLeft, BoundRight>> binder) { if (binder == null) throw new NullPointerException("Binder must not be null"); return binder.apply(leftVal, rightVal); } @Override - public <BoundLeft> IPair<BoundLeft, RightType> - bindLeft(final Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { + public <BoundLeft> Pair<BoundLeft, RightType> + bindLeft(final Function<LeftType, Pair<BoundLeft, RightType>> leftBinder) { if (leftBinder == null) throw new NullPointerException("Left binder must not be null"); if (isLeft) return leftBinder.apply(leftVal); @@ -90,8 +90,8 @@ public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { } @Override - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - final Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { + public <BoundRight> Pair<LeftType, BoundRight> bindRight( + final Function<RightType, Pair<LeftType, BoundRight>> rightBinder) { if (rightBinder == null) throw new NullPointerException("Right binder must not be null"); if (isLeft) return new Either<>(leftVal, null); @@ -100,8 +100,8 @@ public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { @Override public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> - IPair<CombinedLeft, CombinedRight> - combine(final IPair<OtherLeft, OtherRight> otherPair, + Pair<CombinedLeft, CombinedRight> + combine(final Pair<OtherLeft, OtherRight> otherPair, final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, final BiFunction<RightType, OtherRight, CombinedRight> rightCombiner) { @@ -129,7 +129,7 @@ public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { } @Override - public <NewLeft> IPair<NewLeft, RightType> + public <NewLeft> Pair<NewLeft, RightType> mapLeft(final Function<LeftType, NewLeft> mapper) { if (mapper == null) throw new NullPointerException("Mapper must not be null"); @@ -138,7 +138,7 @@ public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { } @Override - public <NewRight> IPair<LeftType, NewRight> + public <NewRight> Pair<LeftType, NewRight> mapRight(final Function<RightType, NewRight> mapper) { if (mapper == null) throw new NullPointerException("Mapper must not be null"); diff --git a/src/main/java/bjc/data/IHolder.java b/src/main/java/bjc/data/Holder.java index e0d39aa..f01812e 100644 --- a/src/main/java/bjc/data/IHolder.java +++ b/src/main/java/bjc/data/Holder.java @@ -18,7 +18,7 @@ import bjc.funcdata.theory.Functor; * @param <ContainedType> * The type of value held. */ -public interface IHolder<ContainedType> extends Functor<ContainedType> { +public interface Holder<ContainedType> extends Functor<ContainedType> { /** * Bind a function across the value in this container. * @@ -30,8 +30,8 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return A holder from binding the value. */ - public <BoundType> IHolder<BoundType> - bind(Function<ContainedType, IHolder<BoundType>> binder); + public <BoundType> Holder<BoundType> + bind(Function<ContainedType, Holder<BoundType>> binder); /** * Apply an action to the value. @@ -51,14 +51,14 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { default <ArgType, ReturnType> Function<Functor<ArgType>, Functor<ReturnType>> fmap(final Function<ArgType, ReturnType> func) { return argumentFunctor -> { - if (!(argumentFunctor instanceof IHolder<?>)) { + if (!(argumentFunctor instanceof Holder<?>)) { final String msg = "This functor only supports mapping over instances of IHolder"; throw new IllegalArgumentException(msg); } - final IHolder<ArgType> holder = (IHolder<ArgType>) argumentFunctor; + final Holder<ArgType> holder = (Holder<ArgType>) argumentFunctor; return holder.map(func); }; @@ -80,7 +80,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return The function lifted over the holder. */ - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(Function<ContainedType, NewType> func); /** @@ -88,7 +88,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return A lazy version of this holder. */ - public default IHolder<ContainedType> makeLazy() { + public default Holder<ContainedType> makeLazy() { return new WrappedLazy<>(this); } @@ -97,7 +97,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return A list version of this holder. */ - public default IHolder<ContainedType> makeList() { + public default Holder<ContainedType> makeList() { return new BoundListHolder<>(new FunctionalList<>(this)); } @@ -106,7 +106,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return An optional version of this holder. */ - public default IHolder<ContainedType> makeOptional() { + public default Holder<ContainedType> makeOptional() { return new WrappedOption<>(this); } @@ -123,7 +123,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return A holder with the mapped value */ - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(Function<ContainedType, MappedType> mapper); /** @@ -134,7 +134,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return The holder itself. */ - public default IHolder<ContainedType> replace(final ContainedType newValue) { + public default Holder<ContainedType> replace(final ContainedType newValue) { return transform(oldValue -> newValue); } @@ -146,7 +146,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return The holder itself, for easy chaining. */ - public IHolder<ContainedType> transform(UnaryOperator<ContainedType> transformer); + public Holder<ContainedType> transform(UnaryOperator<ContainedType> transformer); /** * Unwrap the value contained in this holder so that it is no longer held. @@ -171,7 +171,7 @@ public interface IHolder<ContainedType> extends Functor<ContainedType> { * * @return An instance of IHolder containing that value. */ - static <ElementType> IHolder<ElementType> of(ElementType contained) { + static <ElementType> Holder<ElementType> of(ElementType contained) { return new Identity<>(contained); } } diff --git a/src/main/java/bjc/data/IPair.java b/src/main/java/bjc/data/IPair.java deleted file mode 100644 index f7d7956..0000000 --- a/src/main/java/bjc/data/IPair.java +++ /dev/null @@ -1,250 +0,0 @@ -package bjc.data; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Function; - -import bjc.funcdata.theory.Bifunctor; - -/** - * 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> extends Bifunctor<LeftType, RightType> { - /** - * 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); - - /** - * 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); - - /** - * Pairwise combine two pairs together. - * - * @param <OtherLeft> - * The left type of the other pair. - * - * @param <OtherRight> - * The right type of the other pair. - * - * @param otherPair - * The pair to combine with. - * - * @return The pairs, pairwise combined together. - */ - public default <OtherLeft, OtherRight> - IPair<IPair<LeftType, OtherLeft>, IPair<RightType, OtherRight>> - combine(final IPair<OtherLeft, OtherRight> otherPair) { - return combine(otherPair, - Pair<LeftType, OtherLeft>::new, - Pair<RightType, OtherRight>::new); - } - - /** - * Combine the contents of two pairs together. - * - * @param <OtherLeft> - * The type of the left value of the other pair. - * - * @param <OtherRight> - * The type of the right value of the other pair. - * - * @param <CombinedLeft> - * The type of the left value of the combined pair. - * - * @param <CombinedRight> - * The type of the right value of the combined pair. - * - * @param otherPair - * The other pair to combine with. - * - * @param leftCombiner - * The function to combine the left values with. - * - * @param rightCombiner - * The function to combine the right values with. - * - * @return A pair with its values combined. - */ - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> - IPair<CombinedLeft, CombinedRight> - combine(IPair<OtherLeft, OtherRight> otherPair, - BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, - BiFunction<RightType, OtherRight, CombinedRight> rightCombiner); - - /** - * Immediately perfom the specified action with the contents of this pair. - * - * @param consumer - * The action to perform on the pair. - */ - public default void doWith(final BiConsumer<LeftType, RightType> consumer) { - merge((leftValue, rightValue) -> { - consumer.accept(leftValue, rightValue); - - return null; - }); - } - - @Override - default <OldLeft, OldRight, NewLeft> LeftBifunctorMap<OldLeft, OldRight, NewLeft> - fmapLeft(final Function<OldLeft, NewLeft> func) { - return argumentPair -> { - if (!(argumentPair instanceof IPair<?, ?>)) { - final String msg - = "This function can only be applied to instances of IPair"; - - throw new IllegalArgumentException(msg); - } - - final IPair<OldLeft, OldRight> argPair - = (IPair<OldLeft, OldRight>) argumentPair; - - return argPair.mapLeft(func); - }; - } - - @Override - default <OldLeft, OldRight, NewRight> RightBifunctorMap<OldLeft, OldRight, NewRight> - fmapRight(final Function<OldRight, NewRight> func) { - return argumentPair -> { - if (!(argumentPair instanceof IPair<?, ?>)) { - final String msg - = "This function can only be applied to instances of IPair"; - - throw new IllegalArgumentException(msg); - } - - final IPair<OldLeft, OldRight> argPair - = (IPair<OldLeft, OldRight>) argumentPair; - - return argPair.mapRight(func); - }; - } - - /** - * Get the value on the left side of the pair. - * - * @return The value on the left side of the pair. - */ - @Override - 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. - */ - @Override - public default RightType getRight() { - return merge((leftValue, rightValue) -> rightValue); - } - - /** - * Transform the value on the left side of the pair. - * - * Doesn't modify the pair. - * - * @param <NewLeft> - * The new type of the left part of the pair. - * - * @param mapper - * The function to use to transform the left part of the pair. - * - * @return The pair, with its left part transformed. - */ - public <NewLeft> IPair<NewLeft, RightType> - mapLeft(Function<LeftType, NewLeft> mapper); - - /** - * Transform the value on the right side of the pair. - * - * Doesn't modify the pair. - * - * @param <NewRight> - * The new type of the right part of the pair. - * - * @param mapper - * The function to use to transform the right part of the - * pair. - * - * @return The pair, with its right part transformed. - */ - public <NewRight> IPair<LeftType, NewRight> - mapRight(Function<RightType, NewRight> mapper); - - /** - * 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); - - /** - * Static pair constructor. - * - * @param left - * The left side of the pair. - * @param right - * The right side of the pair. - * @return A pair, with the specified left/right side. - */ - public static <T1, T2> IPair<T1, T2> pair(T1 left, T2 right) { - return new Pair<>(left, right); - } -} diff --git a/src/main/java/bjc/data/ITree.java b/src/main/java/bjc/data/ITree.java deleted file mode 100644 index 7f9c67e..0000000 --- a/src/main/java/bjc/data/ITree.java +++ /dev/null @@ -1,286 +0,0 @@ -package bjc.data; - -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -import bjc.funcdata.IList; -import bjc.funcdata.bst.TreeLinearizationMethod; - -/** - * A node in a homogeneous tree with a unlimited amount of children. - * - * @author ben - * - * @param <ContainedType> - * The type of data contained in the tree nodes. - * - */ -public interface ITree<ContainedType> { - /** - * Append a child to this node. - * - * @param child - * The child to append to this node. - */ - void addChild(ITree<ContainedType> child); - - /** - * Append a child to this node. - * - * @param child - * The child to append to this node. - */ - void addChild(ContainedType child); - - /** - * Prepend a child to this node. - * - * @param child - * The child to prepend to this node. - */ - void prependChild(ITree<ContainedType> child); - - /** - * Collapse a tree into a single version. - * - * @param <NewType> - * The intermediate type being folded. - * - * @param <ReturnedType> - * The type that is the end result. - * - * @param leafTransform - * The function to use to convert leaf values. - * - * @param nodeCollapser - * The function to use to convert internal nodes and - * their children. - * - * @param resultTransformer - * The function to use to convert a state to the - * returned version. - * - * @return The final transformed state. - */ - <NewType, ReturnedType> ReturnedType collapse( - Function<ContainedType, NewType> leafTransform, - BiFunction<ContainedType, IList<NewType>, NewType> nodeCollapser, - Function<NewType, ReturnedType> resultTransformer); - - /** - * Execute a given action for each of this tree's children. - * - * @param action - * The action to execute for each child. - */ - void doForChildren(Consumer<ITree<ContainedType>> action); - - /** - * Expand the nodes of a tree into trees, and then merge the contents of those - * trees into a single tree. - * - * @param mapper - * The function to use to map values into trees. - * - * @return A tree, with some nodes expanded into trees. - */ - default ITree<ContainedType> - flatMapTree(final Function<ContainedType, ITree<ContainedType>> mapper) { - return topDownTransform(dat -> TopDownTransformResult.PUSHDOWN, node -> { - if (node.getChildrenCount() > 0) { - final ITree<ContainedType> parent = node.transformHead(mapper); - - node.doForChildren(parent::addChild); - - return parent; - } - - return node.transformHead(mapper); - }); - } - - /** - * Get the specified child of this tree. - * - * @param childNo - * The number of the child to get. - * - * @return The specified child of this tree. - */ - default ITree<ContainedType> getChild(final int childNo) { - return transformChild(childNo, child -> child); - } - - /** - * Get a count of the number of direct children this node has. - * - * @return The number of direct children this node has. - */ - int getChildrenCount(); - - /** - * Get a count of the number of direct children this node has. - * - * @return The number of direct children this node has. - */ - default int size() { - return getChildrenCount(); - } - - /** - * Get the data stored in this node. - * - * @return The data stored in this node. - */ - default ContainedType getHead() { - return transformHead(head -> head); - } - - /** - * Rebuild the tree with the same structure, but different nodes. - * - * @param <MappedType> - * The type of the new tree. - * - * @param leafTransformer - * The function to use to transform leaf tokens. - * - * @param internalTransformer - * The function to use to transform internal tokens. - * - * @return The tree, with the nodes changed. - */ - <MappedType> ITree<MappedType> rebuildTree( - Function<ContainedType, MappedType> leafTransformer, - Function<ContainedType, MappedType> internalTransformer); - - /** - * Transform some of the nodes in this tree. - * - * @param nodePicker - * The predicate to use to pick nodes to transform. - * - * @param transformer - * The function to use to transform picked nodes. - */ - void selectiveTransform(Predicate<ContainedType> nodePicker, - UnaryOperator<ContainedType> transformer); - - /** - * Do a top-down transform of the tree. - * - * @param transformPicker - * The function to use to pick how to progress. - * - * @param transformer - * The function used to transform picked subtrees. - * - * @return The tree with the transform applied to picked subtrees. - */ - ITree<ContainedType> topDownTransform( - Function<ContainedType, TopDownTransformResult> transformPicker, - UnaryOperator<ITree<ContainedType>> transformer); - - /** - * Transform one of this nodes children. - * - * @param <TransformedType> - * The type of the transformed value. - * - * @param childNo - * The number of the child to transform. - * - * @param transformer - * The function to use to transform the value. - * - * @return The transformed value. - * - * @throws IllegalArgumentException - * if the childNo is out of bounds (0 <= - * childNo <= childCount()). - */ - <TransformedType> TransformedType transformChild(int childNo, - Function<ITree<ContainedType>, TransformedType> transformer); - - /** - * Transform the value that is the head of this node. - * - * @param <TransformedType> - * The type of the transformed value. - * - * @param transformer - * The function to use to transform the value. - * - * @return The transformed value. - */ - <TransformedType> TransformedType - transformHead(Function<ContainedType, TransformedType> transformer); - - /** - * Transform the tree into a tree with a different type of token. - * - * @param <MappedType> - * The type of the new tree. - * - * @param transformer - * The function to use to transform tokens. - * - * @return A tree with the token types transformed. - */ - default <MappedType> ITree<MappedType> - transformTree(final Function<ContainedType, MappedType> transformer) { - return rebuildTree(transformer, transformer); - } - - /** - * Perform an action on each part of the tree. - * - * @param linearizationMethod - * The way to traverse the tree. - * - * @param action - * The action to perform on each tree node. - */ - void traverse(TreeLinearizationMethod linearizationMethod, - Consumer<ContainedType> action); - - /** - * Find the farthest to right child that satisfies the given predicate. - * - * @param childPred - * The predicate to satisfy. - * - * @return The index of the right-most child that satisfies the predicate, or -1 - * if one doesn't exist. - */ - int revFind(Predicate<ITree<ContainedType>> childPred); - - /** - * Check if this tree contains any nodes that satisfy the predicate. - * - * @param pred - * The predicate to look for. - * - * @return Whether or not any items satisfied the predicate. - */ - default boolean containsMatching(Predicate<ContainedType> pred) { - Toggle<Boolean> tog = new OneWayToggle<>(false, true); - - traverse(TreeLinearizationMethod.POSTORDER, val -> { - if (pred.test(val)) tog.get(); - }); - - return tog.get(); - } - - /** - * Set the head of the tree. - * - * @param dat - * The value to set as the head of the tree. - */ - void setHead(ContainedType dat); -} diff --git a/src/main/java/bjc/data/Identity.java b/src/main/java/bjc/data/Identity.java index 75b4ecd..e488072 100644 --- a/src/main/java/bjc/data/Identity.java +++ b/src/main/java/bjc/data/Identity.java @@ -11,7 +11,7 @@ import java.util.function.UnaryOperator; * @param <ContainedType> * The type contained in the holder. */ -public class Identity<ContainedType> implements IHolder<ContainedType> { +public class Identity<ContainedType> implements Holder<ContainedType> { /* The held value. */ private ContainedType heldValue; @@ -31,8 +31,8 @@ public class Identity<ContainedType> implements IHolder<ContainedType> { } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { return binder.apply(heldValue); } @@ -64,7 +64,7 @@ public class Identity<ContainedType> implements IHolder<ContainedType> { } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { return val -> { return new Identity<>(func.apply(val)); @@ -72,7 +72,7 @@ public class Identity<ContainedType> implements IHolder<ContainedType> { } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { return new Identity<>(mapper.apply(heldValue)); } @@ -83,7 +83,7 @@ public class Identity<ContainedType> implements IHolder<ContainedType> { } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { heldValue = transformer.apply(heldValue); diff --git a/src/main/java/bjc/data/Lazy.java b/src/main/java/bjc/data/Lazy.java index 8573325..5fcd2ae 100644 --- a/src/main/java/bjc/data/Lazy.java +++ b/src/main/java/bjc/data/Lazy.java @@ -6,7 +6,7 @@ import java.util.function.UnaryOperator; import bjc.data.internals.BoundLazy; import bjc.funcdata.FunctionalList; -import bjc.funcdata.IList; +import bjc.funcdata.ListEx; /** * A holder that holds a means to create a value, but doesn't actually compute @@ -17,7 +17,7 @@ import bjc.funcdata.IList; * @param <ContainedType> * The type of the value being held. */ -public class Lazy<ContainedType> implements IHolder<ContainedType> { +public class Lazy<ContainedType> implements Holder<ContainedType> { /* The supplier of the type. */ private Supplier<ContainedType> valueSupplier; /* The actual type value. */ @@ -26,7 +26,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { private boolean valueMaterialized; /* The list of pending actions on the value. */ - private IList<UnaryOperator<ContainedType>> actions = new FunctionalList<>(); + private ListEx<UnaryOperator<ContainedType>> actions = new FunctionalList<>(); /** * Create a new lazy value from the specified seed value. @@ -54,16 +54,16 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { /* Create a new value from a supplier and a list of actions. */ private Lazy(final Supplier<ContainedType> supp, - final IList<UnaryOperator<ContainedType>> pendingActions) { + final ListEx<UnaryOperator<ContainedType>> pendingActions) { valueSupplier = supp; actions = pendingActions; } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { + final ListEx<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); for (UnaryOperator<ContainedType> action : actions) { pendingActions.add(action); @@ -79,15 +79,15 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { return val -> new Lazy<>(func.apply(val)); } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); + final ListEx<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); for (UnaryOperator<ContainedType> action : actions) { pendingActions.add(action); @@ -126,7 +126,7 @@ public class Lazy<ContainedType> implements IHolder<ContainedType> { } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { actions.add(transformer); diff --git a/src/main/java/bjc/data/LazyPair.java b/src/main/java/bjc/data/LazyPair.java index 2481cd7..048254a 100644 --- a/src/main/java/bjc/data/LazyPair.java +++ b/src/main/java/bjc/data/LazyPair.java @@ -18,7 +18,7 @@ import bjc.data.internals.HalfBoundLazyPair; * @param <RightType> * The type on the right side of the pair. */ -public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> { +public class LazyPair<LeftType, RightType> implements Pair<LeftType, RightType> { /* The supplier for the left value. */ private Supplier<LeftType> leftSupplier; /* The left value. */ @@ -70,14 +70,14 @@ public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> } @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { + public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> bind( + final BiFunction<LeftType, RightType, Pair<BoundLeft, BoundRight>> binder) { return new BoundLazyPair<>(leftSupplier, rightSupplier, binder); } @Override - public <BoundLeft> IPair<BoundLeft, RightType> - bindLeft(final Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { + public <BoundLeft> Pair<BoundLeft, RightType> + bindLeft(final Function<LeftType, Pair<BoundLeft, RightType>> leftBinder) { final Supplier<LeftType> leftSupp = () -> { if (leftMaterialized) return leftValue; @@ -88,8 +88,8 @@ public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> } @Override - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - final Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { + public <BoundRight> Pair<LeftType, BoundRight> bindRight( + final Function<RightType, Pair<LeftType, BoundRight>> rightBinder) { final Supplier<RightType> rightSupp = () -> { if (rightMaterialized) return rightValue; @@ -101,8 +101,8 @@ public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> @Override public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> - IPair<CombinedLeft, CombinedRight> - combine(final IPair<OtherLeft, OtherRight> otherPair, + Pair<CombinedLeft, CombinedRight> + combine(final Pair<OtherLeft, OtherRight> otherPair, final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, final BiFunction<RightType, OtherRight, CombinedRight> rightCombiner) { @@ -139,7 +139,7 @@ public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> } @Override - public <NewLeft> IPair<NewLeft, RightType> + public <NewLeft> Pair<NewLeft, RightType> mapLeft(final Function<LeftType, NewLeft> mapper) { final Supplier<NewLeft> leftSupp = () -> { if (leftMaterialized) return mapper.apply(leftValue); @@ -157,7 +157,7 @@ public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> } @Override - public <NewRight> IPair<LeftType, NewRight> + public <NewRight> Pair<LeftType, NewRight> mapRight(final Function<RightType, NewRight> mapper) { final Supplier<LeftType> leftSupp = () -> { if (leftMaterialized) return leftValue; diff --git a/src/main/java/bjc/data/ListHolder.java b/src/main/java/bjc/data/ListHolder.java index 79c900d..c8a75ff 100644 --- a/src/main/java/bjc/data/ListHolder.java +++ b/src/main/java/bjc/data/ListHolder.java @@ -5,7 +5,7 @@ import java.util.function.UnaryOperator; import bjc.data.internals.BoundListHolder; import bjc.funcdata.FunctionalList; -import bjc.funcdata.IList; +import bjc.funcdata.ListEx; /** * A holder that represents a set of non-deterministic computations. @@ -15,8 +15,8 @@ import bjc.funcdata.IList; * @param <ContainedType> * The type of contained value. */ -public class ListHolder<ContainedType> implements IHolder<ContainedType> { - private IList<ContainedType> heldValues; +public class ListHolder<ContainedType> implements Holder<ContainedType> { + private ListEx<ContainedType> heldValues; /** * Create a new list holder. @@ -36,34 +36,34 @@ public class ListHolder<ContainedType> implements IHolder<ContainedType> { } /* Create a new holder with values. */ - private ListHolder(final IList<ContainedType> toHold) { + private ListHolder(final ListEx<ContainedType> toHold) { heldValues = toHold; } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IList<IHolder<BoundType>> boundValues = heldValues.map(binder); + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { + final ListEx<Holder<BoundType>> boundValues = heldValues.map(binder); return new BoundListHolder<>(boundValues); } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { return val -> new ListHolder<>(new FunctionalList<>(func.apply(val))); } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IList<MappedType> mappedValues = heldValues.map(mapper); + final ListEx<MappedType> mappedValues = heldValues.map(mapper); return new ListHolder<>(mappedValues); } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { heldValues = heldValues.map(transformer); diff --git a/src/main/java/bjc/data/Option.java b/src/main/java/bjc/data/Option.java index 84e71a2..6c76d59 100644 --- a/src/main/java/bjc/data/Option.java +++ b/src/main/java/bjc/data/Option.java @@ -11,7 +11,7 @@ import java.util.function.UnaryOperator; * @param <ContainedType> * The type of the value that may or may not be held. */ -public class Option<ContainedType> implements IHolder<ContainedType> { +public class Option<ContainedType> implements Holder<ContainedType> { private ContainedType held; /** @@ -25,21 +25,21 @@ public class Option<ContainedType> implements IHolder<ContainedType> { } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { if (held == null) return new Option<>(null); return binder.apply(held); } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { return val -> new Option<>(func.apply(val)); } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { if (held == null) return new Option<>(null); @@ -47,7 +47,7 @@ public class Option<ContainedType> implements IHolder<ContainedType> { } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { if (held != null) held = transformer.apply(held); diff --git a/src/main/java/bjc/data/Pair.java b/src/main/java/bjc/data/Pair.java index ea2f82f..42a28f8 100644 --- a/src/main/java/bjc/data/Pair.java +++ b/src/main/java/bjc/data/Pair.java @@ -1,154 +1,250 @@ package bjc.data; +import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; +import bjc.funcdata.theory.Bifunctor; + /** - * A pair of values, with nothing special about them. + * Represents a pair of values. * * @author ben * * @param <LeftType> - * The type of the left value. + * The type of the left side of the pair. * * @param <RightType> - * The type of the right value. + * The type of the right side of the pair. + * */ -public class Pair<LeftType, RightType> implements IPair<LeftType, RightType> { - /* The left value. */ - private LeftType leftValue; - /* The right value. */ - private RightType rightValue; - - /** Create a new pair with both sides set to null. */ - public Pair() { - // Do nothing :) - } - +public interface Pair<LeftType, RightType> extends Bifunctor<LeftType, RightType> { /** - * Create a new pair with both sides set to the specified values. + * Bind a function across the values in this pair. * - * @param left - * The value of the left side. + * @param <BoundLeft> + * The type of the bound left. * - * @param right - * The value of the right side. + * @param <BoundRight> + * The type of the bound right. + * + * @param binder + * The function to bind with. + * + * @return The bound pair. */ - public Pair(final LeftType left, final RightType right) { - leftValue = left; - rightValue = right; - } - - @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { - if (binder == null) throw new NullPointerException("Binder must not be null."); + public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> + bind(BiFunction<LeftType, RightType, Pair<BoundLeft, BoundRight>> binder); - return binder.apply(leftValue, rightValue); - } + /** + * 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> Pair<BoundLeft, RightType> + bindLeft(Function<LeftType, Pair<BoundLeft, RightType>> leftBinder); - @Override - public <BoundLeft> IPair<BoundLeft, RightType> - bindLeft(final Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { - if (leftBinder == null) throw new NullPointerException("Binder must not be null"); + /** + * 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> Pair<LeftType, BoundRight> + bindRight(Function<RightType, Pair<LeftType, BoundRight>> rightBinder); - return leftBinder.apply(leftValue); + /** + * Pairwise combine two pairs together. + * + * @param <OtherLeft> + * The left type of the other pair. + * + * @param <OtherRight> + * The right type of the other pair. + * + * @param otherPair + * The pair to combine with. + * + * @return The pairs, pairwise combined together. + */ + public default <OtherLeft, OtherRight> + Pair<Pair<LeftType, OtherLeft>, Pair<RightType, OtherRight>> + combine(final Pair<OtherLeft, OtherRight> otherPair) { + return combine(otherPair, + SimplePair<LeftType, OtherLeft>::new, + SimplePair<RightType, OtherRight>::new); } - @Override - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - final Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { - if (rightBinder == null) throw new NullPointerException("Binder must not be null"); + /** + * Combine the contents of two pairs together. + * + * @param <OtherLeft> + * The type of the left value of the other pair. + * + * @param <OtherRight> + * The type of the right value of the other pair. + * + * @param <CombinedLeft> + * The type of the left value of the combined pair. + * + * @param <CombinedRight> + * The type of the right value of the combined pair. + * + * @param otherPair + * The other pair to combine with. + * + * @param leftCombiner + * The function to combine the left values with. + * + * @param rightCombiner + * The function to combine the right values with. + * + * @return A pair with its values combined. + */ + public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> + Pair<CombinedLeft, CombinedRight> + combine(Pair<OtherLeft, OtherRight> otherPair, + BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, + BiFunction<RightType, OtherRight, CombinedRight> rightCombiner); - return rightBinder.apply(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(final BiConsumer<LeftType, RightType> consumer) { + merge((leftValue, rightValue) -> { + consumer.accept(leftValue, rightValue); - @Override - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> - IPair<CombinedLeft, CombinedRight> - combine(final IPair<OtherLeft, OtherRight> otherPair, - final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, - final BiFunction<RightType, OtherRight, - CombinedRight> rightCombiner) { - return otherPair.bind((otherLeft, otherRight) -> { - final CombinedLeft left = leftCombiner.apply(leftValue, otherLeft); - final CombinedRight right = rightCombiner.apply(rightValue, otherRight); - - return new Pair<>(left, right); + return null; }); } @Override - public <NewLeft> IPair<NewLeft, RightType> - mapLeft(final Function<LeftType, NewLeft> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); + default <OldLeft, OldRight, NewLeft> LeftBifunctorMap<OldLeft, OldRight, NewLeft> + fmapLeft(final Function<OldLeft, NewLeft> func) { + return argumentPair -> { + if (!(argumentPair instanceof Pair<?, ?>)) { + final String msg + = "This function can only be applied to instances of IPair"; - return new Pair<>(mapper.apply(leftValue), rightValue); - } + throw new IllegalArgumentException(msg); + } - @Override - public <NewRight> IPair<LeftType, NewRight> - mapRight(final Function<RightType, NewRight> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); + final Pair<OldLeft, OldRight> argPair + = (Pair<OldLeft, OldRight>) argumentPair; - return new Pair<>(leftValue, mapper.apply(rightValue)); + return argPair.mapLeft(func); + }; } @Override - public <MergedType> MergedType - merge(final BiFunction<LeftType, RightType, MergedType> merger) { - if (merger == null) throw new NullPointerException("Merger must not be null"); + default <OldLeft, OldRight, NewRight> RightBifunctorMap<OldLeft, OldRight, NewRight> + fmapRight(final Function<OldRight, NewRight> func) { + return argumentPair -> { + if (!(argumentPair instanceof Pair<?, ?>)) { + final String msg + = "This function can only be applied to instances of IPair"; - return merger.apply(leftValue, rightValue); - } + throw new IllegalArgumentException(msg); + } - @Override - public String toString() { - return String.format("Pair [leftValue='%s', rightValue='%s']", leftValue, - rightValue); + final Pair<OldLeft, OldRight> argPair + = (Pair<OldLeft, OldRight>) argumentPair; + + return argPair.mapRight(func); + }; } + /** + * Get the value on the left side of the pair. + * + * @return The value on the left side of the pair. + */ @Override - public LeftType getLeft() { - return leftValue; + 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. + */ @Override - public RightType getRight() { - return rightValue; + public default RightType getRight() { + return merge((leftValue, rightValue) -> rightValue); } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; + /** + * Transform the value on the left side of the pair. + * + * Doesn't modify the pair. + * + * @param <NewLeft> + * The new type of the left part of the pair. + * + * @param mapper + * The function to use to transform the left part of the pair. + * + * @return The pair, with its left part transformed. + */ + public <NewLeft> Pair<NewLeft, RightType> + mapLeft(Function<LeftType, NewLeft> mapper); - result = prime * result + (leftValue == null ? 0 : leftValue.hashCode()); - result = prime * result + (rightValue == null ? 0 : rightValue.hashCode()); + /** + * Transform the value on the right side of the pair. + * + * Doesn't modify the pair. + * + * @param <NewRight> + * The new type of the right part of the pair. + * + * @param mapper + * The function to use to transform the right part of the + * pair. + * + * @return The pair, with its right part transformed. + */ + public <NewRight> Pair<LeftType, NewRight> + mapRight(Function<RightType, NewRight> mapper); - return result; - } + /** + * 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); - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Pair<?, ?>)) return false; - - final Pair<?, ?> other = (Pair<?, ?>) obj; - - if (leftValue == null) { - if (other.leftValue != null) return false; - } else if (!leftValue.equals(other.leftValue)) { - return false; - } - - if (rightValue == null) { - if (other.rightValue != null) return false; - } else if (!rightValue.equals(other.rightValue)) { - return false; - } - - return true; + /** + * Static pair constructor. + * + * @param left + * The left side of the pair. + * @param right + * The right side of the pair. + * @return A pair, with the specified left/right side. + */ + public static <T1, T2> Pair<T1, T2> pair(T1 left, T2 right) { + return new SimplePair<>(left, right); } } diff --git a/src/main/java/bjc/data/SimplePair.java b/src/main/java/bjc/data/SimplePair.java new file mode 100644 index 0000000..48f5ca3 --- /dev/null +++ b/src/main/java/bjc/data/SimplePair.java @@ -0,0 +1,154 @@ +package bjc.data; + +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 SimplePair<LeftType, RightType> implements Pair<LeftType, RightType> { + /* The left value. */ + private LeftType leftValue; + /* The right value. */ + private RightType rightValue; + + /** Create a new pair with both sides set to null. */ + public SimplePair() { + // Do nothing :) + } + + /** + * 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 SimplePair(final LeftType left, final RightType right) { + leftValue = left; + rightValue = right; + } + + @Override + public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> bind( + final BiFunction<LeftType, RightType, Pair<BoundLeft, BoundRight>> binder) { + if (binder == null) throw new NullPointerException("Binder must not be null."); + + return binder.apply(leftValue, rightValue); + } + + @Override + public <BoundLeft> Pair<BoundLeft, RightType> + bindLeft(final Function<LeftType, Pair<BoundLeft, RightType>> leftBinder) { + if (leftBinder == null) throw new NullPointerException("Binder must not be null"); + + return leftBinder.apply(leftValue); + } + + @Override + public <BoundRight> Pair<LeftType, BoundRight> bindRight( + final Function<RightType, Pair<LeftType, BoundRight>> rightBinder) { + if (rightBinder == null) throw new NullPointerException("Binder must not be null"); + + return rightBinder.apply(rightValue); + } + + @Override + public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> + Pair<CombinedLeft, CombinedRight> + combine(final Pair<OtherLeft, OtherRight> otherPair, + final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, + final BiFunction<RightType, OtherRight, + CombinedRight> rightCombiner) { + return otherPair.bind((otherLeft, otherRight) -> { + final CombinedLeft left = leftCombiner.apply(leftValue, otherLeft); + final CombinedRight right = rightCombiner.apply(rightValue, otherRight); + + return new SimplePair<>(left, right); + }); + } + + @Override + public <NewLeft> Pair<NewLeft, RightType> + mapLeft(final Function<LeftType, NewLeft> mapper) { + if (mapper == null) throw new NullPointerException("Mapper must not be null"); + + return new SimplePair<>(mapper.apply(leftValue), rightValue); + } + + @Override + public <NewRight> Pair<LeftType, NewRight> + mapRight(final Function<RightType, NewRight> mapper) { + if (mapper == null) throw new NullPointerException("Mapper must not be null"); + + return new SimplePair<>(leftValue, mapper.apply(rightValue)); + } + + @Override + public <MergedType> MergedType + merge(final BiFunction<LeftType, RightType, MergedType> merger) { + if (merger == null) throw new NullPointerException("Merger must not be null"); + + return merger.apply(leftValue, rightValue); + } + + @Override + public String toString() { + return String.format("Pair [leftValue='%s', rightValue='%s']", leftValue, + rightValue); + } + + @Override + public LeftType getLeft() { + return leftValue; + } + + @Override + public RightType getRight() { + return rightValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + + result = prime * result + (leftValue == null ? 0 : leftValue.hashCode()); + result = prime * result + (rightValue == null ? 0 : rightValue.hashCode()); + + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SimplePair<?, ?>)) return false; + + final SimplePair<?, ?> other = (SimplePair<?, ?>) obj; + + if (leftValue == null) { + if (other.leftValue != null) return false; + } else if (!leftValue.equals(other.leftValue)) { + return false; + } + + if (rightValue == null) { + if (other.rightValue != null) return false; + } else if (!rightValue.equals(other.rightValue)) { + return false; + } + + return true; + } +} diff --git a/src/main/java/bjc/data/SimpleTree.java b/src/main/java/bjc/data/SimpleTree.java new file mode 100644 index 0000000..7d9fb6d --- /dev/null +++ b/src/main/java/bjc/data/SimpleTree.java @@ -0,0 +1,446 @@ +package bjc.data; + +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +import bjc.funcdata.FunctionalList; +import bjc.funcdata.ListEx; +import bjc.funcdata.bst.TreeLinearizationMethod; + +/** + * A node in a homogeneous tree. + * + * @author ben + * + * @param <ContainedType> + * The type contained in the tree. + */ +public class SimpleTree<ContainedType> implements Tree<ContainedType> { + /* The data/label for this node. */ + private ContainedType data; + + /* The children of this node. */ + private ListEx<Tree<ContainedType>> children; + + /* Whether this node has children. */ + /* + * @NOTE Why have both this boolean and childCount? Why not just do a childCount + * == 0 whenever you'd check hasChildren? + * + * - Because hasChildren is set once and not reset, and really what it + * indicates is that children has been allocated. + */ + private boolean hasChildren; + /* The number of children this node has. */ + private int childCount = 0; + + /* The ID of this node. */ + private int ID; + /* The next ID to assign to a node. */ + private static int nextID = 0; + + /** + * Create a new leaf node in a tree. + */ + public SimpleTree() { + this(null); + } + + /** + * Create a new leaf node in a tree. + * + * @param leaf + * The data to store as a leaf node. + */ + public SimpleTree(final ContainedType leaf) { + data = leaf; + + hasChildren = false; + + ID = nextID++; + } + + /** + * Create a new tree node with the specified children. + * + * @param leaf + * The data to hold in this node. + * + * @param childrn + * A list of children for this node. + */ + public SimpleTree(final ContainedType leaf, final ListEx<Tree<ContainedType>> childrn) { + this(leaf); + + hasChildren = true; + + childCount = childrn.getSize(); + + children = childrn; + } + + /** + * Create a new tree node with the specified children. + * + * @param leaf + * The data to hold in this node. + * + * @param childrn + * A list of children for this node. + */ + @SafeVarargs + public SimpleTree(final ContainedType leaf, final Tree<ContainedType>... childrn) { + this(leaf); + + hasChildren = true; + + childCount = 0; + + children = new FunctionalList<>(); + + for (final Tree<ContainedType> child : childrn) { + children.add(child); + + childCount++; + } + } + + @Override + public void addChild(final ContainedType child) { + addChild(new SimpleTree<>(child)); + } + + @Override + public void addChild(final Tree<ContainedType> child) { + if (hasChildren == false) { + hasChildren = true; + + children = new FunctionalList<>(); + } + + childCount++; + + children.add(child); + } + + @Override + public void prependChild(final Tree<ContainedType> child) { + if (hasChildren == false) { + hasChildren = true; + + children = new FunctionalList<>(); + } + + childCount++; + + children.prepend(child); + } + + @Override + public void doForChildren(final Consumer<Tree<ContainedType>> action) { + if (childCount > 0) children.forEach(action); + } + + @Override + public int getChildrenCount() { + return childCount; + } + + @Override + public int revFind(final Predicate<Tree<ContainedType>> childPred) { + if (childCount == 0) return -1; + + for (int i = childCount - 1; i >= 0; i--) { + if (childPred.test(getChild(i))) return i; + } + + return -1; + } + + @Override + public void traverse(final TreeLinearizationMethod linearizationMethod, + final Consumer<ContainedType> action) { + if (hasChildren) { + switch (linearizationMethod) { + case INORDER: + if (childCount != 2) { + final String msg = "Can only do in-order traversal for binary trees."; + + throw new IllegalArgumentException(msg); + } + + children.getByIndex(0).traverse(linearizationMethod, action); + + action.accept(data); + + children.getByIndex(1).traverse(linearizationMethod, action); + break; + case POSTORDER: + children.forEach(child -> child.traverse(linearizationMethod, action)); + + action.accept(data); + break; + case PREORDER: + action.accept(data); + + children.forEach(child -> child.traverse(linearizationMethod, action)); + break; + default: + break; + + } + } else { + action.accept(data); + } + } + + @Override + public <NewType, ReturnedType> ReturnedType collapse( + final Function<ContainedType, NewType> leafTransform, + final BiFunction<ContainedType, ListEx<NewType>, NewType> nodeCollapser, + final Function<NewType, ReturnedType> resultTransformer) { + return resultTransformer.apply(internalCollapse(leafTransform, nodeCollapser)); + } + + @Override + public Tree<ContainedType> + flatMapTree(final Function<ContainedType, Tree<ContainedType>> mapper) { + if (hasChildren) { + final Tree<ContainedType> flatMappedData = mapper.apply(data); + + final ListEx<Tree<ContainedType>> mappedChildren + = children.map(child -> child.flatMapTree(mapper)); + + mappedChildren.forEach(flatMappedData::addChild); + + return flatMappedData; + } + + return mapper.apply(data); + } + + /* + * Do a collapse of this tree. + */ + + private <NewType> NewType internalCollapse( + final Function<ContainedType, NewType> leafTransform, + final BiFunction<ContainedType, ListEx<NewType>, NewType> nodeCollapser) { + if (hasChildren) { + final ListEx<NewType> collapsedChildren = children.map(child -> { + final NewType collapsed = child.collapse(leafTransform, nodeCollapser, + subTreeVal -> subTreeVal); + + return collapsed; + }); + + return nodeCollapser.apply(data, collapsedChildren); + } + + return leafTransform.apply(data); + } + + private void internalToString(final StringBuilder builder, final int indentLevel, + final boolean initial) { + if (!initial) { + for (int i = 0; i < indentLevel; i++) builder.append(">\t"); + } + + builder.append("Node #"); + builder.append(ID); + builder.append(": "); + builder.append(data == null ? "(null)" : data.toString()); + builder.append("\n"); + + if (hasChildren) { + children.forEach(child -> { + if (child instanceof SimpleTree<?>) { + final SimpleTree<ContainedType> kid = (SimpleTree<ContainedType>) child; + + kid.internalToString(builder, indentLevel + 1, false); + } else { + for (int i = 0; i < indentLevel + 1; i++) { + builder.append(">\t"); + } + + builder.append("Unknown node of type "); + builder.append(child.getClass().getName()); + builder.append("\n"); + } + }); + } + } + + @Override + public <MappedType> Tree<MappedType> rebuildTree( + final Function<ContainedType, MappedType> leafTransformer, + final Function<ContainedType, MappedType> operatorTransformer) { + if (hasChildren) { + final ListEx<Tree<MappedType>> mappedChildren = + children.map(child -> + child.rebuildTree(leafTransformer, operatorTransformer)); + + final MappedType mapData = operatorTransformer.apply(data); + return new SimpleTree<>(mapData, mappedChildren); + } + + return new SimpleTree<>(leafTransformer.apply(data)); + } + + @Override + public void selectiveTransform(final Predicate<ContainedType> nodePicker, + final UnaryOperator<ContainedType> transformer) { + if (hasChildren) { + children.forEach(child -> child.selectiveTransform(nodePicker, transformer)); + } else { + data = transformer.apply(data); + } + } + + @Override + public Tree<ContainedType> topDownTransform( + final Function<ContainedType, TopDownTransformResult> transformPicker, + final UnaryOperator<Tree<ContainedType>> transformer) { + final TopDownTransformResult transformResult = transformPicker.apply(data); + + switch (transformResult) { + case PASSTHROUGH: + Tree<ContainedType> result = new SimpleTree<>(data); + + if (hasChildren) { + children.forEach(child -> { + final Tree<ContainedType> kid + = child.topDownTransform(transformPicker, transformer); + + result.addChild(kid); + }); + } + + return result; + case SKIP: + return this; + case TRANSFORM: + return transformer.apply(this); + case RTRANSFORM: + return transformer.apply(this).topDownTransform(transformPicker, transformer); + case PUSHDOWN: + result = new SimpleTree<>(data); + + if (hasChildren) { + children.forEach(child -> { + final Tree<ContainedType> kid + = child.topDownTransform(transformPicker, transformer); + + result.addChild(kid); + }); + } + + return transformer.apply(result); + case PULLUP: + final Tree<ContainedType> intermediateResult = transformer.apply(this); + + result = new SimpleTree<>(intermediateResult.getHead()); + + intermediateResult.doForChildren(child -> { + final Tree<ContainedType> kid + = child.topDownTransform(transformPicker, transformer); + + result.addChild(kid); + }); + + return result; + default: + final String msg = String.format("Recieved unknown transform result type %s", + transformResult); + + throw new IllegalArgumentException(msg); + } + } + + @Override + public <TransformedType> TransformedType transformChild(final int childNo, + final Function<Tree<ContainedType>, TransformedType> transformer) { + if (childNo < 0 || childNo > childCount - 1) { + final String msg = String.format("Child index #%d is invalid", childNo); + + throw new IllegalArgumentException(msg); + } + + final Tree<ContainedType> selectedKid = children.getByIndex(childNo); + + return transformer.apply(selectedKid); + } + + @Override + public Tree<ContainedType> getChild(final int childNo) { + if (childNo < 0 || childNo > childCount - 1) { + final String msg = String.format("Child index #%d is invalid", childNo); + + throw new IllegalArgumentException(msg); + } + return children.getByIndex(childNo); + } + + @Override + public <TransformedType> TransformedType + transformHead(final Function<ContainedType, TransformedType> transformer) { + return transformer.apply(data); + } + + @Override + public void setHead(ContainedType dat) { + this.data = dat; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + + result = prime * result + childCount; + result = prime * result + (children == null ? 0 : children.hashCode()); + result = prime * result + (data == null ? 0 : data.hashCode()); + + return result; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + + internalToString(builder, 1, true); + + /* Delete a trailing nl. */ + builder.deleteCharAt(builder.length() - 1); + + return builder.toString(); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SimpleTree<?>)) return false; + + final SimpleTree<?> other = (SimpleTree<?>) obj; + + if (data == null) { + if (other.data != null) return false; + } else if (!data.equals(other.data)) { + return false; + } + + if (childCount != other.childCount) return false; + + if (children == null) { + if (other.children != null) return false; + } else if (!children.equals(other.children)) { + return false; + } + + return true; + } +} diff --git a/src/main/java/bjc/data/TopDownTransformIterator.java b/src/main/java/bjc/data/TopDownTransformIterator.java index cf211d3..28df590 100644 --- a/src/main/java/bjc/data/TopDownTransformIterator.java +++ b/src/main/java/bjc/data/TopDownTransformIterator.java @@ -26,7 +26,7 @@ import java.util.function.Function; * The type of the nodes in the tree. */ public class TopDownTransformIterator<ContainedType> - implements Iterator<ITree<ContainedType>> { + implements Iterator<Tree<ContainedType>> { /** * Alias type for a tree transformation. * @@ -35,8 +35,8 @@ public class TopDownTransformIterator<ContainedType> * @param <ContainedType> * The type contained in the tree. */ - public interface TreeTransform<ContainedType> extends BiFunction<ITree<ContainedType>, - Consumer<Iterator<ITree<ContainedType>>>, ITree<ContainedType>> { + public interface TreeTransform<ContainedType> extends BiFunction<Tree<ContainedType>, + Consumer<Iterator<Tree<ContainedType>>>, Tree<ContainedType>> { // Alias type; no body is needed } @@ -49,19 +49,19 @@ public class TopDownTransformIterator<ContainedType> */ private final TreeTransform<ContainedType> transform; - private ITree<ContainedType> preParent; - private ITree<ContainedType> postParent; + private Tree<ContainedType> preParent; + private Tree<ContainedType> postParent; - private final Deque<ITree<ContainedType>> preChildren; - private final Deque<ITree<ContainedType>> postChildren; + private final Deque<Tree<ContainedType>> preChildren; + private final Deque<Tree<ContainedType>> postChildren; private TopDownTransformIterator<ContainedType> curChild; private boolean done; private boolean initial; - private final Deque<Iterator<ITree<ContainedType>>> toYield; - private Iterator<ITree<ContainedType>> currYield; + private final Deque<Iterator<Tree<ContainedType>>> toYield; + private Iterator<Tree<ContainedType>> currYield; /** * Create a new tree iterator. @@ -76,7 +76,7 @@ public class TopDownTransformIterator<ContainedType> public TopDownTransformIterator( final Function<ContainedType, TopDownTransformResult> pickr, final TreeTransform<ContainedType> transfrm, - final ITree<ContainedType> tree) { + final Tree<ContainedType> tree) { preParent = tree; preChildren = new LinkedList<>(); @@ -96,7 +96,7 @@ public class TopDownTransformIterator<ContainedType> * @param src * The nodes to yield. */ - public void addYield(final Iterator<ITree<ContainedType>> src) { + public void addYield(final Iterator<Tree<ContainedType>> src) { if (currYield != null) toYield.push(currYield); currYield = src; @@ -115,7 +115,7 @@ public class TopDownTransformIterator<ContainedType> * * @return The next yielded value. */ - public ITree<ContainedType> flushYields(final ITree<ContainedType> val) { + public Tree<ContainedType> flushYields(final Tree<ContainedType> val) { if (currYield != null) { /* * We have non-sentinel values to yield. @@ -144,14 +144,14 @@ public class TopDownTransformIterator<ContainedType> } @Override - public ITree<ContainedType> next() { + public Tree<ContainedType> next() { if (done) throw new NoSuchElementException(); /* * Flush any values that need to be yielded. */ if (currYield != null) { - ITree<ContainedType> yeld = flushYields(null); + Tree<ContainedType> yeld = flushYields(null); if (yeld != null) return yeld; } @@ -164,7 +164,7 @@ public class TopDownTransformIterator<ContainedType> switch (res) { case PASSTHROUGH: - postParent = new Tree<>(preParent.getHead()); + postParent = new SimpleTree<>(preParent.getHead()); if (preParent.getChildrenCount() != 0) { for (int i = 0; i < preParent.getChildrenCount(); i++) { @@ -198,12 +198,12 @@ public class TopDownTransformIterator<ContainedType> done = true; return flushYields( - transform.apply(new Tree<>(preParent.getHead()), this::addYield)); + transform.apply(new SimpleTree<>(preParent.getHead()), this::addYield)); case PULLUP: - final ITree<ContainedType> intRes + final Tree<ContainedType> intRes = transform.apply(preParent, this::addYield); - postParent = new Tree<>(intRes.getHead()); + postParent = new SimpleTree<>(intRes.getHead()); if (intRes.getChildrenCount() != 0) { for (int i = 0; i < intRes.getChildrenCount(); i++) { @@ -228,22 +228,22 @@ public class TopDownTransformIterator<ContainedType> curChild = new TopDownTransformIterator<>(picker, transform, preChildren.pop()); - final ITree<ContainedType> res = curChild.next(); + final Tree<ContainedType> res = curChild.next(); // System.out.println("\t\tTRACE: adding node " + res + " to children"); postChildren.add(res); return flushYields(res); } - ITree<ContainedType> res = null; + Tree<ContainedType> res = null; if (postParent == null) { - res = new Tree<>(preParent.getHead()); + res = new SimpleTree<>(preParent.getHead()); // System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + // res); - for (final ITree<ContainedType> child : postChildren) { + for (final Tree<ContainedType> child : postChildren) { res.addChild(child); } @@ -254,7 +254,7 @@ public class TopDownTransformIterator<ContainedType> // System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + // res); - for (final ITree<ContainedType> child : postChildren) { + for (final Tree<ContainedType> child : postChildren) { res.addChild(child); } } @@ -263,7 +263,7 @@ public class TopDownTransformIterator<ContainedType> return flushYields(res); } - final ITree<ContainedType> res = curChild.next(); + final Tree<ContainedType> res = curChild.next(); // System.out.println("\t\tTRACE: adding node " + res + " to children"); postChildren.add(res); diff --git a/src/main/java/bjc/data/Tree.java b/src/main/java/bjc/data/Tree.java index d0cfe3d..3e16e02 100644 --- a/src/main/java/bjc/data/Tree.java +++ b/src/main/java/bjc/data/Tree.java @@ -6,441 +6,281 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; -import bjc.funcdata.FunctionalList; -import bjc.funcdata.IList; +import bjc.funcdata.ListEx; import bjc.funcdata.bst.TreeLinearizationMethod; /** - * A node in a homogeneous tree. + * A node in a homogeneous tree with a unlimited amount of children. * * @author ben * * @param <ContainedType> - * The type contained in the tree. + * The type of data contained in the tree nodes. + * */ -public class Tree<ContainedType> implements ITree<ContainedType> { - /* The data/label for this node. */ - private ContainedType data; - - /* The children of this node. */ - private IList<ITree<ContainedType>> children; - - /* Whether this node has children. */ - /* - * @NOTE Why have both this boolean and childCount? Why not just do a childCount - * == 0 whenever you'd check hasChildren? - * - * - Because hasChildren is set once and not reset, and really what it - * indicates is that children has been allocated. +public interface Tree<ContainedType> { + /** + * Append a child to this node. + * + * @param child + * The child to append to this node. */ - private boolean hasChildren; - /* The number of children this node has. */ - private int childCount = 0; - - /* The ID of this node. */ - private int ID; - /* The next ID to assign to a node. */ - private static int nextID = 0; + void addChild(Tree<ContainedType> child); /** - * Create a new leaf node in a tree. + * Append a child to this node. + * + * @param child + * The child to append to this node. */ - public Tree() { - this(null); - } + void addChild(ContainedType child); /** - * Create a new leaf node in a tree. + * Prepend a child to this node. * - * @param leaf - * The data to store as a leaf node. + * @param child + * The child to prepend to this node. */ - public Tree(final ContainedType leaf) { - data = leaf; - - hasChildren = false; - - ID = nextID++; - } + void prependChild(Tree<ContainedType> child); /** - * Create a new tree node with the specified children. + * Collapse a tree into a single version. + * + * @param <NewType> + * The intermediate type being folded. + * + * @param <ReturnedType> + * The type that is the end result. + * + * @param leafTransform + * The function to use to convert leaf values. + * + * @param nodeCollapser + * The function to use to convert internal nodes and + * their children. * - * @param leaf - * The data to hold in this node. + * @param resultTransformer + * The function to use to convert a state to the + * returned version. * - * @param childrn - * A list of children for this node. + * @return The final transformed state. */ - public Tree(final ContainedType leaf, final IList<ITree<ContainedType>> childrn) { - this(leaf); + <NewType, ReturnedType> ReturnedType collapse( + Function<ContainedType, NewType> leafTransform, + BiFunction<ContainedType, ListEx<NewType>, NewType> nodeCollapser, + Function<NewType, ReturnedType> resultTransformer); - hasChildren = true; - - childCount = childrn.getSize(); - - children = childrn; - } + /** + * Execute a given action for each of this tree's children. + * + * @param action + * The action to execute for each child. + */ + void doForChildren(Consumer<Tree<ContainedType>> action); /** - * Create a new tree node with the specified children. + * Expand the nodes of a tree into trees, and then merge the contents of those + * trees into a single tree. * - * @param leaf - * The data to hold in this node. + * @param mapper + * The function to use to map values into trees. * - * @param childrn - * A list of children for this node. + * @return A tree, with some nodes expanded into trees. */ - @SafeVarargs - public Tree(final ContainedType leaf, final ITree<ContainedType>... childrn) { - this(leaf); - - hasChildren = true; - - childCount = 0; - - children = new FunctionalList<>(); - - for (final ITree<ContainedType> child : childrn) { - children.add(child); - - childCount++; - } - } - - @Override - public void addChild(final ContainedType child) { - addChild(new Tree<>(child)); - } - - @Override - public void addChild(final ITree<ContainedType> child) { - if (hasChildren == false) { - hasChildren = true; - - children = new FunctionalList<>(); - } - - childCount++; - - children.add(child); - } - - @Override - public void prependChild(final ITree<ContainedType> child) { - if (hasChildren == false) { - hasChildren = true; - - children = new FunctionalList<>(); - } - - childCount++; - - children.prepend(child); - } - - @Override - public void doForChildren(final Consumer<ITree<ContainedType>> action) { - if (childCount > 0) children.forEach(action); - } - - @Override - public int getChildrenCount() { - return childCount; - } - - @Override - public int revFind(final Predicate<ITree<ContainedType>> childPred) { - if (childCount == 0) return -1; - - for (int i = childCount - 1; i >= 0; i--) { - if (childPred.test(getChild(i))) return i; - } - - return -1; - } - - @Override - public void traverse(final TreeLinearizationMethod linearizationMethod, - final Consumer<ContainedType> action) { - if (hasChildren) { - switch (linearizationMethod) { - case INORDER: - if (childCount != 2) { - final String msg = "Can only do in-order traversal for binary trees."; - - throw new IllegalArgumentException(msg); - } - - children.getByIndex(0).traverse(linearizationMethod, action); + default Tree<ContainedType> + flatMapTree(final Function<ContainedType, Tree<ContainedType>> mapper) { + return topDownTransform(dat -> TopDownTransformResult.PUSHDOWN, node -> { + if (node.getChildrenCount() > 0) { + final Tree<ContainedType> parent = node.transformHead(mapper); - action.accept(data); - - children.getByIndex(1).traverse(linearizationMethod, action); - break; - case POSTORDER: - children.forEach(child -> child.traverse(linearizationMethod, action)); - - action.accept(data); - break; - case PREORDER: - action.accept(data); - - children.forEach(child -> child.traverse(linearizationMethod, action)); - break; - default: - break; + node.doForChildren(parent::addChild); + return parent; } - } else { - action.accept(data); - } - } - - @Override - public <NewType, ReturnedType> ReturnedType collapse( - final Function<ContainedType, NewType> leafTransform, - final BiFunction<ContainedType, IList<NewType>, NewType> nodeCollapser, - final Function<NewType, ReturnedType> resultTransformer) { - return resultTransformer.apply(internalCollapse(leafTransform, nodeCollapser)); - } - - @Override - public ITree<ContainedType> - flatMapTree(final Function<ContainedType, ITree<ContainedType>> mapper) { - if (hasChildren) { - final ITree<ContainedType> flatMappedData = mapper.apply(data); - - final IList<ITree<ContainedType>> mappedChildren - = children.map(child -> child.flatMapTree(mapper)); - - mappedChildren.forEach(flatMappedData::addChild); - - return flatMappedData; - } - return mapper.apply(data); + return node.transformHead(mapper); + }); } - /* - * Do a collapse of this tree. + /** + * Get the specified child of this tree. + * + * @param childNo + * The number of the child to get. + * + * @return The specified child of this tree. */ - - private <NewType> NewType internalCollapse( - final Function<ContainedType, NewType> leafTransform, - final BiFunction<ContainedType, IList<NewType>, NewType> nodeCollapser) { - if (hasChildren) { - final IList<NewType> collapsedChildren = children.map(child -> { - final NewType collapsed = child.collapse(leafTransform, nodeCollapser, - subTreeVal -> subTreeVal); - - return collapsed; - }); - - return nodeCollapser.apply(data, collapsedChildren); - } - - return leafTransform.apply(data); - } - - private void internalToString(final StringBuilder builder, final int indentLevel, - final boolean initial) { - if (!initial) { - for (int i = 0; i < indentLevel; i++) builder.append(">\t"); - } - - builder.append("Node #"); - builder.append(ID); - builder.append(": "); - builder.append(data == null ? "(null)" : data.toString()); - builder.append("\n"); - - if (hasChildren) { - children.forEach(child -> { - if (child instanceof Tree<?>) { - final Tree<ContainedType> kid = (Tree<ContainedType>) child; - - kid.internalToString(builder, indentLevel + 1, false); - } else { - for (int i = 0; i < indentLevel + 1; i++) { - builder.append(">\t"); - } - - builder.append("Unknown node of type "); - builder.append(child.getClass().getName()); - builder.append("\n"); - } - }); - } + default Tree<ContainedType> getChild(final int childNo) { + return transformChild(childNo, child -> child); } - @Override - public <MappedType> ITree<MappedType> rebuildTree( - final Function<ContainedType, MappedType> leafTransformer, - final Function<ContainedType, MappedType> operatorTransformer) { - if (hasChildren) { - final IList<ITree<MappedType>> mappedChildren = - children.map(child -> - child.rebuildTree(leafTransformer, operatorTransformer)); - - final MappedType mapData = operatorTransformer.apply(data); - return new Tree<>(mapData, mappedChildren); - } - - return new Tree<>(leafTransformer.apply(data)); - } + /** + * Get a count of the number of direct children this node has. + * + * @return The number of direct children this node has. + */ + int getChildrenCount(); - @Override - public void selectiveTransform(final Predicate<ContainedType> nodePicker, - final UnaryOperator<ContainedType> transformer) { - if (hasChildren) { - children.forEach(child -> child.selectiveTransform(nodePicker, transformer)); - } else { - data = transformer.apply(data); - } + /** + * Get a count of the number of direct children this node has. + * + * @return The number of direct children this node has. + */ + default int size() { + return getChildrenCount(); } - @Override - public ITree<ContainedType> topDownTransform( - final Function<ContainedType, TopDownTransformResult> transformPicker, - final UnaryOperator<ITree<ContainedType>> transformer) { - final TopDownTransformResult transformResult = transformPicker.apply(data); - - switch (transformResult) { - case PASSTHROUGH: - ITree<ContainedType> result = new Tree<>(data); - - if (hasChildren) { - children.forEach(child -> { - final ITree<ContainedType> kid - = child.topDownTransform(transformPicker, transformer); - - result.addChild(kid); - }); - } - - return result; - case SKIP: - return this; - case TRANSFORM: - return transformer.apply(this); - case RTRANSFORM: - return transformer.apply(this).topDownTransform(transformPicker, transformer); - case PUSHDOWN: - result = new Tree<>(data); - - if (hasChildren) { - children.forEach(child -> { - final ITree<ContainedType> kid - = child.topDownTransform(transformPicker, transformer); - - result.addChild(kid); - }); - } - - return transformer.apply(result); - case PULLUP: - final ITree<ContainedType> intermediateResult = transformer.apply(this); - - result = new Tree<>(intermediateResult.getHead()); - - intermediateResult.doForChildren(child -> { - final ITree<ContainedType> kid - = child.topDownTransform(transformPicker, transformer); - - result.addChild(kid); - }); - - return result; - default: - final String msg = String.format("Recieved unknown transform result type %s", - transformResult); - - throw new IllegalArgumentException(msg); - } + /** + * Get the data stored in this node. + * + * @return The data stored in this node. + */ + default ContainedType getHead() { + return transformHead(head -> head); } - @Override - public <TransformedType> TransformedType transformChild(final int childNo, - final Function<ITree<ContainedType>, TransformedType> transformer) { - if (childNo < 0 || childNo > childCount - 1) { - final String msg = String.format("Child index #%d is invalid", childNo); - - throw new IllegalArgumentException(msg); - } - - final ITree<ContainedType> selectedKid = children.getByIndex(childNo); + /** + * Rebuild the tree with the same structure, but different nodes. + * + * @param <MappedType> + * The type of the new tree. + * + * @param leafTransformer + * The function to use to transform leaf tokens. + * + * @param internalTransformer + * The function to use to transform internal tokens. + * + * @return The tree, with the nodes changed. + */ + <MappedType> Tree<MappedType> rebuildTree( + Function<ContainedType, MappedType> leafTransformer, + Function<ContainedType, MappedType> internalTransformer); - return transformer.apply(selectedKid); - } + /** + * Transform some of the nodes in this tree. + * + * @param nodePicker + * The predicate to use to pick nodes to transform. + * + * @param transformer + * The function to use to transform picked nodes. + */ + void selectiveTransform(Predicate<ContainedType> nodePicker, + UnaryOperator<ContainedType> transformer); - @Override - public ITree<ContainedType> getChild(final int childNo) { - if (childNo < 0 || childNo > childCount - 1) { - final String msg = String.format("Child index #%d is invalid", childNo); + /** + * Do a top-down transform of the tree. + * + * @param transformPicker + * The function to use to pick how to progress. + * + * @param transformer + * The function used to transform picked subtrees. + * + * @return The tree with the transform applied to picked subtrees. + */ + Tree<ContainedType> topDownTransform( + Function<ContainedType, TopDownTransformResult> transformPicker, + UnaryOperator<Tree<ContainedType>> transformer); - throw new IllegalArgumentException(msg); - } - return children.getByIndex(childNo); - } + /** + * Transform one of this nodes children. + * + * @param <TransformedType> + * The type of the transformed value. + * + * @param childNo + * The number of the child to transform. + * + * @param transformer + * The function to use to transform the value. + * + * @return The transformed value. + * + * @throws IllegalArgumentException + * if the childNo is out of bounds (0 <= + * childNo <= childCount()). + */ + <TransformedType> TransformedType transformChild(int childNo, + Function<Tree<ContainedType>, TransformedType> transformer); - @Override - public <TransformedType> TransformedType - transformHead(final Function<ContainedType, TransformedType> transformer) { - return transformer.apply(data); - } + /** + * Transform the value that is the head of this node. + * + * @param <TransformedType> + * The type of the transformed value. + * + * @param transformer + * The function to use to transform the value. + * + * @return The transformed value. + */ + <TransformedType> TransformedType + transformHead(Function<ContainedType, TransformedType> transformer); - @Override - public void setHead(ContainedType dat) { - this.data = dat; + /** + * Transform the tree into a tree with a different type of token. + * + * @param <MappedType> + * The type of the new tree. + * + * @param transformer + * The function to use to transform tokens. + * + * @return A tree with the token types transformed. + */ + default <MappedType> Tree<MappedType> + transformTree(final Function<ContainedType, MappedType> transformer) { + return rebuildTree(transformer, transformer); } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + childCount; - result = prime * result + (children == null ? 0 : children.hashCode()); - result = prime * result + (data == null ? 0 : data.hashCode()); - - return result; - } + /** + * Perform an action on each part of the tree. + * + * @param linearizationMethod + * The way to traverse the tree. + * + * @param action + * The action to perform on each tree node. + */ + void traverse(TreeLinearizationMethod linearizationMethod, + Consumer<ContainedType> action); - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); + /** + * Find the farthest to right child that satisfies the given predicate. + * + * @param childPred + * The predicate to satisfy. + * + * @return The index of the right-most child that satisfies the predicate, or -1 + * if one doesn't exist. + */ + int revFind(Predicate<Tree<ContainedType>> childPred); - internalToString(builder, 1, true); + /** + * Check if this tree contains any nodes that satisfy the predicate. + * + * @param pred + * The predicate to look for. + * + * @return Whether or not any items satisfied the predicate. + */ + default boolean containsMatching(Predicate<ContainedType> pred) { + Toggle<Boolean> tog = new OneWayToggle<>(false, true); - /* Delete a trailing nl. */ - builder.deleteCharAt(builder.length() - 1); + traverse(TreeLinearizationMethod.POSTORDER, val -> { + if (pred.test(val)) tog.get(); + }); - return builder.toString(); + return tog.get(); } - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Tree<?>)) return false; - - final Tree<?> other = (Tree<?>) obj; - - if (data == null) { - if (other.data != null) return false; - } else if (!data.equals(other.data)) { - return false; - } - - if (childCount != other.childCount) return false; - - if (children == null) { - if (other.children != null) return false; - } else if (!children.equals(other.children)) { - return false; - } - - return true; - } + /** + * Set the head of the tree. + * + * @param dat + * The value to set as the head of the tree. + */ + void setHead(ContainedType dat); } diff --git a/src/main/java/bjc/data/internals/BoundLazy.java b/src/main/java/bjc/data/internals/BoundLazy.java index a350a2b..0e0e95c 100644 --- a/src/main/java/bjc/data/internals/BoundLazy.java +++ b/src/main/java/bjc/data/internals/BoundLazy.java @@ -4,10 +4,10 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; -import bjc.data.IHolder; +import bjc.data.Holder; import bjc.data.Lazy; import bjc.funcdata.FunctionalList; -import bjc.funcdata.IList; +import bjc.funcdata.ListEx; /** * Implements a lazy holder that has been bound. @@ -19,21 +19,21 @@ import bjc.funcdata.IList; * The type of the new bound value. */ public class BoundLazy<OldType, BoundContainedType> - implements IHolder<BoundContainedType> { + implements Holder<BoundContainedType> { /* The old value. */ - private final Supplier<IHolder<OldType>> oldSupplier; + private final Supplier<Holder<OldType>> oldSupplier; /* The function to use to transform the old value into a new value. */ - private final Function<OldType, IHolder<BoundContainedType>> binder; + private final Function<OldType, Holder<BoundContainedType>> binder; /* The bound value being held. */ - private IHolder<BoundContainedType> boundHolder; + private Holder<BoundContainedType> boundHolder; /* Whether the bound value has been actualized or not. */ private boolean holderBound; /* Transformations currently pending on the bound value. */ - private final IList<UnaryOperator<BoundContainedType>> actions + private final ListEx<UnaryOperator<BoundContainedType>> actions = new FunctionalList<>(); /** @@ -45,20 +45,20 @@ public class BoundLazy<OldType, BoundContainedType> * @param binder * The function to use to bind the old value to the new one. */ - public BoundLazy(final Supplier<IHolder<OldType>> supp, - final Function<OldType, IHolder<BoundContainedType>> binder) { + public BoundLazy(final Supplier<Holder<OldType>> supp, + final Function<OldType, Holder<BoundContainedType>> binder) { oldSupplier = supp; this.binder = binder; } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<BoundContainedType, IHolder<BoundType>> bindr) { + public <BoundType> Holder<BoundType> + bind(final Function<BoundContainedType, Holder<BoundType>> bindr) { if (bindr == null) throw new NullPointerException("Binder must not be null"); /* Prepare a list of pending actions. */ - final IList<UnaryOperator<BoundContainedType>> pendingActions + final ListEx<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>(); for (UnaryOperator<BoundContainedType> pendAct : actions) { @@ -66,8 +66,8 @@ public class BoundLazy<OldType, BoundContainedType> } /* Create the new supplier of a value. */ - final Supplier<IHolder<BoundContainedType>> typeSupplier = () -> { - IHolder<BoundContainedType> oldHolder = boundHolder; + final Supplier<Holder<BoundContainedType>> typeSupplier = () -> { + Holder<BoundContainedType> oldHolder = boundHolder; /* Bind the value if it hasn't been bound before. */ if (!holderBound) { @@ -83,7 +83,7 @@ public class BoundLazy<OldType, BoundContainedType> } @Override - public <NewType> Function<BoundContainedType, IHolder<NewType>> + public <NewType> Function<BoundContainedType, Holder<NewType>> lift(final Function<BoundContainedType, NewType> func) { if (func == null) throw new NullPointerException("Function to lift must not be null"); @@ -94,13 +94,13 @@ public class BoundLazy<OldType, BoundContainedType> } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<BoundContainedType, MappedType> mapper) { if (mapper == null) throw new NullPointerException("Mapper must not be null"); /* Prepare a list of pending actions. */ - final IList<UnaryOperator<BoundContainedType>> pendingActions + final ListEx<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>(); for (UnaryOperator<BoundContainedType> pendAct : actions) { @@ -109,7 +109,7 @@ public class BoundLazy<OldType, BoundContainedType> /* Prepare the new supplier. */ final Supplier<MappedType> typeSupplier = () -> { - IHolder<BoundContainedType> oldHolder = boundHolder; + Holder<BoundContainedType> oldHolder = boundHolder; /* Bound the value if it hasn't been bound. */ if (!holderBound) { @@ -133,7 +133,7 @@ public class BoundLazy<OldType, BoundContainedType> } @Override - public IHolder<BoundContainedType> + public Holder<BoundContainedType> transform(final UnaryOperator<BoundContainedType> transformer) { if (transformer == null) throw new NullPointerException("Transformer must not be null"); diff --git a/src/main/java/bjc/data/internals/BoundLazyPair.java b/src/main/java/bjc/data/internals/BoundLazyPair.java index e081c04..91981de 100644 --- a/src/main/java/bjc/data/internals/BoundLazyPair.java +++ b/src/main/java/bjc/data/internals/BoundLazyPair.java @@ -4,8 +4,8 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; -import bjc.data.IHolder; -import bjc.data.IPair; +import bjc.data.Holder; +import bjc.data.Pair; import bjc.data.Identity; import bjc.data.LazyPair; @@ -16,17 +16,17 @@ import bjc.data.LazyPair; */ @SuppressWarnings("javadoc") public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> - implements IPair<NewLeft, NewRight> { + implements Pair<NewLeft, NewRight> { /* The supplier of the left value. */ private final Supplier<OldLeft> leftSupplier; /* The supplier of the right value. */ private final Supplier<OldRight> rightSupplier; /* The binder to transform values. */ - private final BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> binder; + private final BiFunction<OldLeft, OldRight, Pair<NewLeft, NewRight>> binder; /* The bound pair. */ - private IPair<NewLeft, NewRight> boundPair; + private Pair<NewLeft, NewRight> boundPair; /* Whether the pair has been bound yet. */ private boolean pairBound; @@ -46,20 +46,20 @@ public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> */ public BoundLazyPair(final Supplier<OldLeft> leftSupp, final Supplier<OldRight> rightSupp, - final BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> bindr) { + final BiFunction<OldLeft, OldRight, Pair<NewLeft, NewRight>> bindr) { leftSupplier = leftSupp; rightSupplier = rightSupp; binder = bindr; } @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) { + public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> bind( + final BiFunction<NewLeft, NewRight, Pair<BoundLeft, BoundRight>> bindr) { if (bindr == null) throw new NullPointerException("Binder must not be null"); - final IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(boundPair); - final IHolder<Boolean> newPairMade = new Identity<>(pairBound); + final Holder<Pair<NewLeft, NewRight>> newPair = new Identity<>(boundPair); + final Holder<Boolean> newPairMade = new Identity<>(pairBound); final Supplier<NewLeft> leftSupp = () -> { if (!newPairMade.getValue()) { @@ -91,13 +91,13 @@ public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> } @Override - public <BoundLeft> IPair<BoundLeft, NewRight> - bindLeft(final Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) { + public <BoundLeft> Pair<BoundLeft, NewRight> + bindLeft(final Function<NewLeft, Pair<BoundLeft, NewRight>> leftBinder) { if (leftBinder == null) throw new NullPointerException("Left binder must not be null"); final Supplier<NewLeft> leftSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; + Pair<NewLeft, NewRight> newPair = boundPair; if (!pairBound) { /* @@ -113,13 +113,13 @@ public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> } @Override - public <BoundRight> IPair<NewLeft, BoundRight> - bindRight(final Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) { + public <BoundRight> Pair<NewLeft, BoundRight> + bindRight(final Function<NewRight, Pair<NewLeft, BoundRight>> rightBinder) { if (rightBinder == null) throw new NullPointerException("Right binder must not be null"); final Supplier<NewRight> rightSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; + Pair<NewLeft, NewRight> newPair = boundPair; if (!pairBound) { /* @@ -136,8 +136,8 @@ public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> @Override public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> - IPair<CombinedLeft, CombinedRight> - combine(final IPair<OtherLeft, OtherRight> otherPair, + Pair<CombinedLeft, CombinedRight> + combine(final Pair<OtherLeft, OtherRight> otherPair, final BiFunction<NewLeft, OtherLeft, CombinedLeft> leftCombiner, final BiFunction<NewRight, OtherRight, CombinedRight> rightCombiner) { if (otherPair == null) { @@ -157,7 +157,7 @@ public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> } @Override - public <NewLeftType> IPair<NewLeftType, NewRight> + public <NewLeftType> Pair<NewLeftType, NewRight> mapLeft(final Function<NewLeft, NewLeftType> mapper) { if (mapper == null) throw new NullPointerException("Mapper must not be null"); @@ -184,7 +184,7 @@ public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> } @Override - public <NewRightType> IPair<NewLeft, NewRightType> + public <NewRightType> Pair<NewLeft, NewRightType> mapRight(final Function<NewRight, NewRightType> mapper) { if (mapper == null) throw new NullPointerException("Mapper must not be null"); diff --git a/src/main/java/bjc/data/internals/BoundListHolder.java b/src/main/java/bjc/data/internals/BoundListHolder.java index 1193c8d..c944252 100644 --- a/src/main/java/bjc/data/internals/BoundListHolder.java +++ b/src/main/java/bjc/data/internals/BoundListHolder.java @@ -3,9 +3,9 @@ package bjc.data.internals; import java.util.function.Function; import java.util.function.UnaryOperator; -import bjc.data.IHolder; +import bjc.data.Holder; import bjc.data.ListHolder; -import bjc.funcdata.IList; +import bjc.funcdata.ListEx; /** * Holds a list, converted into a holder. @@ -13,9 +13,9 @@ import bjc.funcdata.IList; * @author Ben Culkin */ @SuppressWarnings("javadoc") -public class BoundListHolder<ContainedType> implements IHolder<ContainedType> { +public class BoundListHolder<ContainedType> implements Holder<ContainedType> { /* The list of contained holders. */ - private final IList<IHolder<ContainedType>> heldHolders; + private final ListEx<Holder<ContainedType>> heldHolders; /** * Create a new list of holders. @@ -23,17 +23,17 @@ public class BoundListHolder<ContainedType> implements IHolder<ContainedType> { * @param toHold * The list of holders to, well, hold. */ - public BoundListHolder(final IList<IHolder<ContainedType>> toHold) { + public BoundListHolder(final ListEx<Holder<ContainedType>> toHold) { heldHolders = toHold; } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { if (binder == null) throw new NullPointerException("Binder must not be null"); - final IList<IHolder<BoundType>> boundHolders + final ListEx<Holder<BoundType>> boundHolders = heldHolders.map(containedHolder -> { return containedHolder.bind(binder); }); @@ -42,7 +42,7 @@ public class BoundListHolder<ContainedType> implements IHolder<ContainedType> { } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { if (func == null) throw new NullPointerException("Function to lift must not be null"); @@ -53,12 +53,12 @@ public class BoundListHolder<ContainedType> implements IHolder<ContainedType> { } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { if (mapper == null) throw new NullPointerException("Mapper must not be null"); - final IList<IHolder<MappedType>> mappedHolders + final ListEx<Holder<MappedType>> mappedHolders = heldHolders.map(containedHolder -> { return containedHolder.map(mapper); }); @@ -67,7 +67,7 @@ public class BoundListHolder<ContainedType> implements IHolder<ContainedType> { } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { if (transformer == null) throw new NullPointerException("Transformer must not be null"); diff --git a/src/main/java/bjc/data/internals/HalfBoundLazyPair.java b/src/main/java/bjc/data/internals/HalfBoundLazyPair.java index 6bcb6ae..849b973 100644 --- a/src/main/java/bjc/data/internals/HalfBoundLazyPair.java +++ b/src/main/java/bjc/data/internals/HalfBoundLazyPair.java @@ -4,8 +4,8 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; -import bjc.data.IHolder; -import bjc.data.IPair; +import bjc.data.Holder; +import bjc.data.Pair; import bjc.data.Identity; import bjc.data.LazyPair; @@ -24,15 +24,15 @@ import bjc.data.LazyPair; */ @SuppressWarnings("javadoc") public class HalfBoundLazyPair<OldType, NewLeft, NewRight> - implements IPair<NewLeft, NewRight> { + implements Pair<NewLeft, NewRight> { /* The supplier of the old value. */ private final Supplier<OldType> oldSupplier; /* The function to transform the old value into a new pair. */ - private final Function<OldType, IPair<NewLeft, NewRight>> binder; + private final Function<OldType, Pair<NewLeft, NewRight>> binder; /* The new bound pair. */ - private IPair<NewLeft, NewRight> boundPair; + private Pair<NewLeft, NewRight> boundPair; /* Has the pair been bound yet or not? */ private boolean pairBound; @@ -46,16 +46,16 @@ public class HalfBoundLazyPair<OldType, NewLeft, NewRight> * The function to use to create the pair from the old value. */ public HalfBoundLazyPair(final Supplier<OldType> oldSupp, - final Function<OldType, IPair<NewLeft, NewRight>> bindr) { + final Function<OldType, Pair<NewLeft, NewRight>> bindr) { oldSupplier = oldSupp; binder = bindr; } @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) { - final IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(boundPair); - final IHolder<Boolean> newPairMade = new Identity<>(pairBound); + public <BoundLeft, BoundRight> Pair<BoundLeft, BoundRight> bind( + final BiFunction<NewLeft, NewRight, Pair<BoundLeft, BoundRight>> bindr) { + final Holder<Pair<NewLeft, NewRight>> newPair = new Identity<>(boundPair); + final Holder<Boolean> newPairMade = new Identity<>(pairBound); final Supplier<NewLeft> leftSupp = () -> { if (!newPairMade.getValue()) { @@ -81,10 +81,10 @@ public class HalfBoundLazyPair<OldType, NewLeft, NewRight> } @Override - public <BoundLeft> IPair<BoundLeft, NewRight> - bindLeft(final Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) { + public <BoundLeft> Pair<BoundLeft, NewRight> + bindLeft(final Function<NewLeft, Pair<BoundLeft, NewRight>> leftBinder) { final Supplier<NewLeft> leftSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; + Pair<NewLeft, NewRight> newPair = boundPair; if (!pairBound) { newPair = binder.apply(oldSupplier.get()); @@ -97,10 +97,10 @@ public class HalfBoundLazyPair<OldType, NewLeft, NewRight> } @Override - public <BoundRight> IPair<NewLeft, BoundRight> - bindRight(final Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) { + public <BoundRight> Pair<NewLeft, BoundRight> + bindRight(final Function<NewRight, Pair<NewLeft, BoundRight>> rightBinder) { final Supplier<NewRight> rightSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; + Pair<NewLeft, NewRight> newPair = boundPair; if (!pairBound) { newPair = binder.apply(oldSupplier.get()); @@ -114,8 +114,8 @@ public class HalfBoundLazyPair<OldType, NewLeft, NewRight> @Override public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> - IPair<CombinedLeft, CombinedRight> - combine(final IPair<OtherLeft, OtherRight> otherPair, + Pair<CombinedLeft, CombinedRight> + combine(final Pair<OtherLeft, OtherRight> otherPair, final BiFunction<NewLeft, OtherLeft, CombinedLeft> leftCombiner, final BiFunction<NewRight, OtherRight, CombinedRight> rightCombiner) { return otherPair.bind((otherLeft, otherRight) -> bind((leftVal, rightVal) -> { @@ -127,7 +127,7 @@ public class HalfBoundLazyPair<OldType, NewLeft, NewRight> } @Override - public <NewLeftType> IPair<NewLeftType, NewRight> + public <NewLeftType> Pair<NewLeftType, NewRight> mapLeft(final Function<NewLeft, NewLeftType> mapper) { final Supplier<NewLeftType> leftSupp = () -> { if (pairBound) @@ -149,7 +149,7 @@ public class HalfBoundLazyPair<OldType, NewLeft, NewRight> } @Override - public <NewRightType> IPair<NewLeft, NewRightType> + public <NewRightType> Pair<NewLeft, NewRightType> mapRight(final Function<NewRight, NewRightType> mapper) { final Supplier<NewLeft> leftSupp = () -> { if (pairBound) diff --git a/src/main/java/bjc/data/internals/WrappedLazy.java b/src/main/java/bjc/data/internals/WrappedLazy.java index cda86fd..624fb1b 100644 --- a/src/main/java/bjc/data/internals/WrappedLazy.java +++ b/src/main/java/bjc/data/internals/WrappedLazy.java @@ -3,7 +3,7 @@ package bjc.data.internals; import java.util.function.Function; import java.util.function.UnaryOperator; -import bjc.data.IHolder; +import bjc.data.Holder; import bjc.data.Lazy; /** @@ -13,9 +13,9 @@ import bjc.data.Lazy; * @param <ContainedType> * The type of the wrapped value. */ -public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { +public class WrappedLazy<ContainedType> implements Holder<ContainedType> { /* Held value. */ - private final IHolder<IHolder<ContainedType>> held; + private final Holder<Holder<ContainedType>> held; /** * Create a new wrapped lazy value. @@ -23,7 +23,7 @@ public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { * @param wrappedHolder * The holder to make lazy. */ - public WrappedLazy(final IHolder<ContainedType> wrappedHolder) { + public WrappedLazy(final Holder<ContainedType> wrappedHolder) { held = new Lazy<>(wrappedHolder); } @@ -34,15 +34,15 @@ public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { * This is a case where reified generics would be useful, because then the * compiler could know which one we meant without the dummy parameter. */ - private WrappedLazy(final IHolder<IHolder<ContainedType>> wrappedHolder, + private WrappedLazy(final Holder<Holder<ContainedType>> wrappedHolder, @SuppressWarnings("unused") final boolean dummy) { held = wrappedHolder; } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IHolder<IHolder<BoundType>> newHolder = held.map(containedHolder -> { + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { + final Holder<Holder<BoundType>> newHolder = held.map(containedHolder -> { return containedHolder.bind(binder); }); @@ -50,7 +50,7 @@ public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { return val -> { return new Lazy<>(func.apply(val)); @@ -58,9 +58,9 @@ public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IHolder<IHolder<MappedType>> newHolder = held.map(containedHolder -> { + final Holder<Holder<MappedType>> newHolder = held.map(containedHolder -> { return containedHolder.map(mapper); }); @@ -68,7 +68,7 @@ public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { held.transform(containedHolder -> { return containedHolder.transform(transformer); diff --git a/src/main/java/bjc/data/internals/WrappedOption.java b/src/main/java/bjc/data/internals/WrappedOption.java index 6becc16..f46d501 100644 --- a/src/main/java/bjc/data/internals/WrappedOption.java +++ b/src/main/java/bjc/data/internals/WrappedOption.java @@ -3,7 +3,7 @@ package bjc.data.internals; import java.util.function.Function; import java.util.function.UnaryOperator; -import bjc.data.IHolder; +import bjc.data.Holder; import bjc.data.Option; /** @@ -13,9 +13,9 @@ import bjc.data.Option; * @param <ContainedType> * The wrapped type. */ -public class WrappedOption<ContainedType> implements IHolder<ContainedType> { +public class WrappedOption<ContainedType> implements Holder<ContainedType> { /* The held value. */ - private final IHolder<IHolder<ContainedType>> held; + private final Holder<Holder<ContainedType>> held; /** * Create a new wrapped option. @@ -23,7 +23,7 @@ public class WrappedOption<ContainedType> implements IHolder<ContainedType> { * @param seedValue * The value to wrap. */ - public WrappedOption(final IHolder<ContainedType> seedValue) { + public WrappedOption(final Holder<ContainedType> seedValue) { held = new Option<>(seedValue); } @@ -31,15 +31,15 @@ public class WrappedOption<ContainedType> implements IHolder<ContainedType> { * The dummy parameter is to ensure the compiler can pick the right method, * because without this method erases to the same type as the public one. */ - private WrappedOption(final IHolder<IHolder<ContainedType>> toHold, + private WrappedOption(final Holder<Holder<ContainedType>> toHold, @SuppressWarnings("unused") final boolean dummy) { held = toHold; } @Override - public <BoundType> IHolder<BoundType> - bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IHolder<IHolder<BoundType>> newHolder = held.map(containedHolder -> { + public <BoundType> Holder<BoundType> + bind(final Function<ContainedType, Holder<BoundType>> binder) { + final Holder<Holder<BoundType>> newHolder = held.map(containedHolder -> { return containedHolder.bind((containedValue) -> { if (containedValue == null) return new Option<>(null); @@ -52,7 +52,7 @@ public class WrappedOption<ContainedType> implements IHolder<ContainedType> { } @Override - public <NewType> Function<ContainedType, IHolder<NewType>> + public <NewType> Function<ContainedType, Holder<NewType>> lift(final Function<ContainedType, NewType> func) { return val -> { return new Option<>(func.apply(val)); @@ -60,9 +60,9 @@ public class WrappedOption<ContainedType> implements IHolder<ContainedType> { } @Override - public <MappedType> IHolder<MappedType> + public <MappedType> Holder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IHolder<IHolder<MappedType>> newHolder = held.map(containedHolder -> { + final Holder<Holder<MappedType>> newHolder = held.map(containedHolder -> { return containedHolder.map((containedValue) -> { if (containedValue == null) return null; @@ -75,7 +75,7 @@ public class WrappedOption<ContainedType> implements IHolder<ContainedType> { } @Override - public IHolder<ContainedType> + public Holder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { held.transform(containedHolder -> { return containedHolder.transform((containedValue) -> { |
