Mercurial > hg > Members > tatsuki > functionaljava-master > core
diff src/main/java/fj/data/Seq.java @ 0:fe80c1edf1be
add getLoop
author | tatsuki |
---|---|
date | Fri, 20 Mar 2015 21:04:03 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/fj/data/Seq.java Fri Mar 20 21:04:03 2015 +0900 @@ -0,0 +1,131 @@ +package fj.data; + +import fj.F; +import fj.F2; +import fj.Function; +import static fj.Bottom.error; +import static fj.Monoid.intAdditionMonoid; +import static fj.data.fingertrees.FingerTree.measured; + +import fj.data.fingertrees.FingerTree; +import fj.data.fingertrees.MakeTree; +import fj.data.fingertrees.Measured; + +/** + * Provides an immutable finite sequence, implemented as a finger tree. This structure gives O(1) access to + * the head and tail, as well as O(log n) random access and concatenation of sequences. + */ +public final class Seq<A> { + private static final Measured<Integer, Object> ELEM_MEASURED = measured(intAdditionMonoid, Function.constant(1)); + private static final MakeTree<Integer, Object> MK_TREE = FingerTree.mkTree(ELEM_MEASURED); + private static final Seq<Object> EMPTY = new Seq<Object>(MK_TREE.empty()); + + @SuppressWarnings("unchecked") + private static <A> MakeTree<Integer, A> mkTree() { + return (MakeTree<Integer, A>) MK_TREE; + } + + private final FingerTree<Integer, A> ftree; + + private Seq(final FingerTree<Integer, A> ftree) { + this.ftree = ftree; + } + + @SuppressWarnings("unchecked") + private static <A> Measured<Integer, A> elemMeasured() { + return (Measured<Integer, A>) ELEM_MEASURED; + } + + /** + * The empty sequence. + * + * @return A sequence with no elements. + */ + @SuppressWarnings("unchecked") + public static <A> Seq<A> empty() { + return (Seq<A>) EMPTY; + } + + /** + * A singleton sequence. + * + * @param a The single element in the sequence. + * @return A new sequence with the given element in it. + */ + public static <A> Seq<A> single(final A a) { + return new Seq<A>(Seq.<A>mkTree().single(a)); + } + + /** + * Inserts the given element at the front of this sequence. + * + * @param a An element to insert at the front of this sequence. + * @return A new sequence with the given element at the front. + */ + public Seq<A> cons(final A a) { + return new Seq<A>(ftree.cons(a)); + } + + /** + * Inserts the given element at the end of this sequence. + * + * @param a An element to insert at the end of this sequence. + * @return A new sequence with the given element at the end. + */ + public Seq<A> snoc(final A a) { + return new Seq<A>(ftree.snoc(a)); + } + + /** + * Appends the given sequence to this sequence. + * + * @param as A sequence to append to this one. + * @return A new sequence with the given sequence appended to this one. + */ + public Seq<A> append(final Seq<A> as) { + return new Seq<A>(ftree.append(as.ftree)); + } + + /** + * Checks if this is the empty sequence. + * + * @return True if this sequence is empty, otherwise false. + */ + public boolean isEmpty() { + return ftree.isEmpty(); + } + + /** + * Returns the number of elements in this sequence. + * + * @return the number of elements in this sequence. + */ + public int length() { + return ftree.measure(); + } + + /** + * Returns the element at the given index. + * + * @param i The index of the element to return. + * @return The element at the given index, or throws an error if the index is out of bounds. + */ + public A index(final int i) { + if (i < 0 || i >= length()) + throw error("Index " + i + "out of bounds."); + return ftree.lookup(Function.<Integer>identity(), i)._2(); + } + + public <B> B foldLeft(final F2<B, A, B> f, final B z) { + return ftree.foldLeft(f, z); + } + + public <B> B foldRight(final F2<A, B, B> f, final B z) { + return ftree.foldRight(f, z); + } + + public <B> Seq<B> map(F<A, B> f) { + return new Seq<B>(ftree.map(f, Seq.<B>elemMeasured())); + } + +}