Package org.organicdesign.fp.xform
Class Xform<A>
- java.lang.Object
-
- org.organicdesign.fp.xform.Xform<A>
-
- All Implemented Interfaces:
Iterable<A>,UnmodIterable<A>,Transformable<A>
public abstract class Xform<A> extends Object implements UnmodIterable<A>
An immutable description of operations to be performed (a transformation, transform, or x-form). When fold() (or another terminating function) is called, the Xform definition is "compiled" into a one-time mutable transformation which is then carried out. This allows certain performance shortcuts (such as doing a drop with index addition instead of iteration) and also hides the mutability otherwise inherent in a transformation. Xform is an abstract class. Most of the methods on Xform produce immutable descriptions of actions to take at a later time. These are represented by ___Desc classes. When fold() is called (or any of the helper methods that wrap it), that produces a result by first stringing together a bunch of Operations (____Op classes) and then "running" them. This is analogous to compiling a program and running it. The ____Desc classes are like the immutable source, the ____Op classes like the op-codes it's compiled into. Special thanks to Nathan Williams for pointing me toward separating the mutation from the description of a transformation. Also, to Paul Phillips (@extempore2) whose lectures provided an outline for what was ideal and also what was important. All errors are my own. -Glen 2015-08-30
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected static classXform.RunListA RunList is a list of Operations "compiled" from an Xform.-
Nested classes/interfaces inherited from interface org.organicdesign.fp.collections.UnmodIterable
UnmodIterable.UnIterable
-
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description @NotNull Xform<A>concat(@Nullable Iterable<? extends A> list)Add items to the end of this Transformable (precat() adds to the beginning)@NotNull Xform<A>drop(long n)The number of items to drop from the beginning of the output.@NotNull Xform<A>dropWhile(@NotNull Fn1<? super A,Boolean> predicate)The number of items to drop from the beginning of the output.static <T> @NotNull Xform<T>empty()@NotNull Xform<A>filter(@NotNull Fn1<? super A,Boolean> f)Return only the items for which the given predicate returns true.<B> @NotNull Xform<B>flatMap(@NotNull Fn1<? super A,Iterable<B>> f)Transform each item into zero or more new items using the given function.<B> Bfold(B ident, @NotNull Fn2<? super B,? super A,B> reducer)Provides a way to collect the results of the transformation.<G,B>
@NotNull Or<G,B>foldUntil(G accum, @Nullable Fn2<? super G,? super A,B> terminator, @NotNull Fn2<? super G,? super A,G> reducer)This implementation should be correct, but could be slow in the case where previous operations are slow and the terminateWhen operation is fast and terminates early.@NotNull UnmodIterator<A>iterator()A one-time use, mutable, not-thread-safe way to get each value of the underling collection in turn.<B> @NotNull Xform<B>map(@NotNull Fn1<? super A,? extends B> f)Transform each item into exactly one new item using the given function.static <T> @NotNull Xform<T>of(@Nullable Iterable<? extends T> list)Static factory methods@NotNull Xform<A>precat(@Nullable Iterable<? extends A> list)Add items to the beginning of this Transformable ("precat" is a PREpending version of conCAT).@NotNull Xform<A>take(long numItems)Return only the first n items.@NotNull Xform<A>takeWhile(@NotNull Fn1<? super A,Boolean> f)Return items from the beginning until the given predicate returns false.protected abstract @NotNull Xform.RunListtoRunList()-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface java.lang.Iterable
forEach, spliterator
-
Methods inherited from interface org.organicdesign.fp.xform.Transformable
any, toImList, toImMap, toImRrbt, toImSet, toImSortedMap, toImSortedSet, toMutList, toMutMap, toMutRrbt, toMutSet, toMutSortedMap, toMutSortedSet
-
Methods inherited from interface org.organicdesign.fp.collections.UnmodIterable
head, whereNonNull
-
-
-
-
Field Detail
-
EMPTY
@NotNull public static final @NotNull Xform EMPTY
-
-
Method Detail
-
empty
@NotNull public static <T> @NotNull Xform<T> empty()
-
of
@NotNull public static <T> @NotNull Xform<T> of(@Nullable @Nullable Iterable<? extends T> list)
Static factory methods
-
iterator
@NotNull public @NotNull UnmodIterator<A> iterator()
Description copied from interface:UnmodIterableA one-time use, mutable, not-thread-safe way to get each value of the underling collection in turn. I experimented with various thread-safe alternatives, but the JVM is optimized around iterators so this is the lowest common denominator of collection iteration, even though iterators are inherently mutable.
-
concat
@NotNull public @NotNull Xform<A> concat(@Nullable @Nullable Iterable<? extends A> list)
Description copied from interface:UnmodIterableAdd items to the end of this Transformable (precat() adds to the beginning)- Specified by:
concatin interfaceTransformable<A>- Specified by:
concatin interfaceUnmodIterable<A>- Parameters:
list- the items to add- Returns:
- a new Transformable with the items added.
-
precat
@NotNull public @NotNull Xform<A> precat(@Nullable @Nullable Iterable<? extends A> list)
Description copied from interface:UnmodIterableAdd items to the beginning of this Transformable ("precat" is a PREpending version of conCAT).- Specified by:
precatin interfaceTransformable<A>- Specified by:
precatin interfaceUnmodIterable<A>- Parameters:
list- the items to add- Returns:
- a new Transformable with the items added.
-
drop
@NotNull public @NotNull Xform<A> drop(long n)
The number of items to drop from the beginning of the output.- Specified by:
dropin interfaceTransformable<A>- Specified by:
dropin interfaceUnmodIterable<A>- Parameters:
n- the number of items at the beginning of this Transformable to ignore- Returns:
- a Transformable with the specified number of items ignored.
-
dropWhile
@NotNull public @NotNull Xform<A> dropWhile(@NotNull @NotNull Fn1<? super A,Boolean> predicate)
The number of items to drop from the beginning of the output.- Specified by:
dropWhilein interfaceTransformable<A>- Specified by:
dropWhilein interfaceUnmodIterable<A>- Parameters:
predicate- the predicate (test function)- Returns:
- a Transformable with the matching leading items ignored.
-
fold
public <B> B fold(B ident, @NotNull @NotNull Fn2<? super B,? super A,B> reducer)Provides a way to collect the results of the transformation.- Specified by:
foldin interfaceTransformable<A>- Specified by:
foldin interfaceUnmodIterable<A>- Parameters:
ident- the accumulator and starting value. This will be passed to the function on the first iteration to be combined with the first member of the underlying data source. For some operations you'll need to pass an identity, e.g. for a sum, pass 0, for a product, pass 1 as this parameter.reducer- combines each value in the list with the result so far. The initial result is u.- Returns:
- an eagerly evaluated result which could be a single value like a sum, or a collection.
-
foldUntil
@NotNull public <G,B> @NotNull Or<G,B> foldUntil(G accum, @Nullable @Nullable Fn2<? super G,? super A,B> terminator, @NotNull @NotNull Fn2<? super G,? super A,G> reducer)
This implementation should be correct, but could be slow in the case where previous operations are slow and the terminateWhen operation is fast and terminates early. It actually renders items to a mutable List, then runs through the list performing the requested reduction, checking for early termination on the result. If you can do a takeWhile() or take() earlier in the transform chain instead of doing it here, always do that. If you really need early termination based on the *result* of a fold, and the operations are expensive or the input is huge, try using a View instead. If you don't care about those things, then this method is perfect for you. Normally you want to terminate by doing a take(), drop(), or takeWhile() before you get to the fold, but if you need to terminate based on the complete result so far, you can provide your own termination condition to this version of fold(). This function can do anything a loop can do. One use case is to accumulate a map and stop if it finds a duplicate key, before overwriting that element in the map. It could then return the map so far, an error, or whatever you like.- Specified by:
foldUntilin interfaceTransformable<A>- Specified by:
foldUntilin interfaceUnmodIterable<A>- Parameters:
accum- the accumulator and starting value. This will be passed to the function on the first iteration to be combined with the first member of the underlying data source. For some operations you'll need to pass an identity, e.g. for a sum, pass 0, for a product, pass 1 as this parameter.terminator- return null to continue processing. Return non-null to terminate the foldUntil and return Or.bad of this value. This function is called at the beginning of each "loop", thus it's first called with the original value of accum and the first item to process. Returning non-null immediately will prevent the reducer from ever being called.reducer- combines each value in the list with the result so far. The initial result is u.- Returns:
- an
Orwhere theOr.good()is an eagerly evaluated result andOr.bad()is whatever terminateWhen returned.
-
filter
@NotNull public @NotNull Xform<A> filter(@NotNull @NotNull Fn1<? super A,Boolean> f)
Description copied from interface:UnmodIterableReturn only the items for which the given predicate returns true.- Specified by:
filterin interfaceTransformable<A>- Specified by:
filterin interfaceUnmodIterable<A>- Parameters:
f- a function that returns true for items to keep, false for items to drop- Returns:
- a Transformable of only the filtered items.
-
flatMap
@NotNull public <B> @NotNull Xform<B> flatMap(@NotNull @NotNull Fn1<? super A,Iterable<B>> f)
Description copied from interface:UnmodIterableTransform each item into zero or more new items using the given function. One of the two higher-order functions that can produce more output items than input items. fold is the other, but flatMap is lazy while fold is eager.- Specified by:
flatMapin interfaceTransformable<A>- Specified by:
flatMapin interfaceUnmodIterable<A>- Parameters:
f- yields a Transformable of 0 or more results for each input item.- Returns:
- a lazily evaluated collection which is expected to be larger than the input collection. For a collection that's the same size, map() is more efficient. If the expected return is smaller, use filter followed by map if possible, or vice versa if not.
-
map
@NotNull public <B> @NotNull Xform<B> map(@NotNull @NotNull Fn1<? super A,? extends B> f)
Description copied from interface:UnmodIterableTransform each item into exactly one new item using the given function.- Specified by:
mapin interfaceTransformable<A>- Specified by:
mapin interfaceUnmodIterable<A>- Parameters:
f- a function that returns a new value for any value in the input- Returns:
- a Transformable of the same size as the input (may contain duplicates) containing the return values of the given function in the same order as the input values.
-
toRunList
@NotNull protected abstract @NotNull Xform.RunList toRunList()
-
take
@NotNull public @NotNull Xform<A> take(long numItems)
Description copied from interface:UnmodIterableReturn only the first n items.- Specified by:
takein interfaceTransformable<A>- Specified by:
takein interfaceUnmodIterable<A>- Parameters:
numItems- the maximum number of items in the returned view.- Returns:
- a Transformable containing no more than the specified number of items.
-
takeWhile
@NotNull public @NotNull Xform<A> takeWhile(@NotNull @NotNull Fn1<? super A,Boolean> f)
Description copied from interface:UnmodIterableReturn items from the beginning until the given predicate returns false.- Specified by:
takeWhilein interfaceTransformable<A>- Specified by:
takeWhilein interfaceUnmodIterable<A>- Parameters:
f- the predicate (test function)- Returns:
- a lazy transformable containing the longest un-interrupted run of items, from the beginning of the transformable, that satisfy the given predicate. This could be 0 items to the entire transformable.
-
-