fj.data.DList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionaljava Show documentation
Show all versions of functionaljava Show documentation
Functional Java is an open source library that supports closures for the Java programming language
package fj.data;
import fj.F;
import fj.P;
import fj.control.Trampoline;
import java.util.Iterator;
import static fj.data.List.iterableList;
/**
* Difference List. It converts left associative appends into right associative ones to improve performance.
*
* @version %build.number%
*/
public final class DList {
private final F,Trampoline>> appendFn;
private DList(final F,Trampoline>> appendFn) {
this.appendFn = appendFn;
}
/**
* Creates a DList from the function
*
* For alternatives functions to create a DList:
* @see #iterableDList
* @see #iteratorDList
* @see #arrayDList
*/
public static DList dlist(final F,Trampoline>> f) {
return new DList<>(f);
}
/**
* Creates a DList from a List
*/
public static DList listDList(final List a) {
return dlist((List tail) -> Trampoline.pure(a.append(tail)));
}
/**
* Creates a DList from an Iterable
*/
public static DList iterableDList(final Iterable it) {
return listDList(iterableList(it));
}
/**
* Creates a DList from an Iterator
*/
public static DList iteratorDList(final Iterator it) {
return iterableDList(() -> it);
}
/**
* Creates a DList from an array
*/
@SafeVarargs
public static DList arrayDList(final A...as) {
return listDList(List.list(as));
}
/**
* Concatenates all the internal Lists together that are held in
* the DList's lambda's state to produce a List.
* This is what converts the appending operation from left associative to right associative,
* giving DList it's speed.
* @return the final List
*/
public List run() {
return appendFn.f(List.nil()).run();
}
/**
* Converts the DList to a standard java.util.List.
*/
public java.util.List toJavaList() {
return run().toJavaList();
}
/**
* A empty DList.
* @param
* @return a empty DList.
*/
public static DList nil() {
return new DList<>(Trampoline.pure());
}
/**
* Produces a DList with one element.
* @param
* @param a the element in the DList.
* @return a DList with one element.
*/
public static DList single(A a) {
return new DList<>((List tail) -> Trampoline.pure(tail.cons(a)));
}
/**
* Prepends a single element on the DList to produce a new DList.
* @param a the element to append.
* @return the new DList.
*/
public DList cons(A a) {
return single(a).append(this);
}
/**
* Appends a single element on the end of the DList to produce a new DList.
* @param a the element to append.
* @return the new DList.
*/
public DList snoc(A a) {
return this.append(single(a));
}
/**
* Appends two DLists together to produce a new DList.
* @param other the other DList to append on the end of this one.
* @return the new DList.
*/
public DList append(DList other) {
return new DList<>(kleisliTrampCompose(this.appendFn, other.appendFn));
}
private static F> kleisliTrampCompose(F> bc, F> ab) {
return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(P.lazy(() -> bc.f(b))));
}
}