
fj.data.DList Maven / Gradle / Ivy
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(() -> bc.f(b)));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy