package com.googlecode.totallylazy.collections; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.Filterable; import com.googlecode.totallylazy.Foldable; import com.googlecode.totallylazy.functions.Function0; import com.googlecode.totallylazy.functions.Curried2; import com.googlecode.totallylazy.Functor; import com.googlecode.totallylazy.Option; import com.googlecode.totallylazy.functions.Function2; import com.googlecode.totallylazy.predicates.Predicate; import com.googlecode.totallylazy.Segment; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.annotations.tailrec; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import static com.googlecode.totallylazy.functions.Callables.returns; import static com.googlecode.totallylazy.Sequences.sequence; public interface PersistentList<T> extends List<T>, PersistentCollection<T>, Iterable<T>, Segment<T>, Indexed<T>, Foldable<T> { @Override PersistentList<T> empty(); @Override PersistentList<T> cons(T head); @Override PersistentList<T> tail() throws NoSuchElementException; default PersistentList<PersistentList<T>> tails() { if(isEmpty()) return constructors.empty(); return constructors.cons(this, tail().tails()); } @Override default <S> S fold(final S seed, final Function2<? super S, ? super T, ? extends S> callable) { return toSequence().fold(seed, callable); } @tailrec default T last() { PersistentList<T> tail = tail(); if(tail.isEmpty()) return head(); return tail.last(); } @tailrec default Option<T> lastOption() { if(isEmpty()) return Option.none(); PersistentList<T> tail = tail(); if(tail.isEmpty()) return headOption(); return tail.lastOption(); } PersistentList<T> append(T value); @Override PersistentList<T> delete(T value); PersistentList<T> reverse(); List<T> toMutableList(); Sequence<T> toSequence(); Zipper<T> zipper(); @Override T get(int index) throws IndexOutOfBoundsException; @Override PersistentList<T> subList(int fromIndex, int toIndex); /** @deprecated Mutation not supported. Replaced by {@link PersistentCollection#cons(T)} */ @Override @Deprecated boolean add(T e); /** @deprecated Mutation not supported. Replaced by {@link PersistentCollection#cons(T)} */ @Override @Deprecated boolean addAll(Collection<? extends T> c); /** @deprecated Mutation not supported. Replaced by {@link PersistentList#append(T)} */ @Override @Deprecated void add(int index, T element); /** @deprecated Mutation not supported. Replaced by {@link PersistentList#append(T)} */ @Override @Deprecated boolean addAll(int index, Collection<? extends T> c); /** @deprecated Mutation not supported. Replaced by {@link PersistentList#append(T)} */ @Override @Deprecated T set(int index, T element); /** @deprecated Mutation not supported. Replaced by {@link PersistentList#append(T)} */ @Override @Deprecated T remove(int index); /** @deprecated Mutation not supported. Replaced by {@link PersistentCollection#delete(T)} */ @Override @Deprecated boolean remove(Object o); /** @deprecated Mutation not supported. Replaced by {@link PersistentCollection#deleteAll(Iterable)}*/ @Override @Deprecated boolean removeAll(Collection<?> c); /** @deprecated Mutation not supported. Replaced by {@link PersistentCollection#filter(Predicate)} */ @Override @Deprecated boolean retainAll(Collection<?> c); /** @deprecated Mutation not supported. Replaced by {@link PersistentCollection#empty()} */ @Override @Deprecated void clear(); class constructors { public static <T> PersistentList<T> empty() { return LinkedList.emptyList(); } public static <T> PersistentList<T> empty(Class<T> aClass) { return empty(); } public static <T> PersistentList<T> cons(T head, PersistentList<T> tail) { return LinkedList.cons(head, tail); } public static <T> PersistentList<T> one(T one) { return cons(one, constructors.<T>empty()); } public static <T> PersistentList<T> list(T one) { return cons(one, constructors.<T>empty()); } public static <T> PersistentList<T> list(T one, T two) { return cons(one, cons(two, constructors.<T>empty())); } public static <T> PersistentList<T> list(T one, T two, T three) { return cons(one, cons(two, cons(three, constructors.<T>empty()))); } public static <T> PersistentList<T> list(T one, T two, T three, T four) { return cons(one, cons(two, cons(three, cons(four, constructors.<T>empty())))); } public static <T> PersistentList<T> list(T one, T two, T three, T four, T five) { return cons(one, cons(two, cons(three, cons(four, cons(five, constructors.<T>empty()))))); } @SafeVarargs public static <T> PersistentList<T> list(T... values) { return list(sequence(values)); } public static <T> PersistentList<T> list(Iterable<? extends T> values) { return sequence(values).reverse().foldLeft(constructors.<T>empty(), functions.<T>cons()); } public static <T> PersistentList<T> reverse(Iterable<? extends T> values) { return reverse(values.iterator()); } public static <T> PersistentList<T> reverse(Iterator<? extends T> iterator) { PersistentList<T> reverse = empty(); while (iterator.hasNext()) { reverse = cons(iterator.next(), reverse); } return reverse; } public static <T> PersistentList<T> reverse(PersistentList<T> list) { PersistentList<T> reverse = list.empty(); for (T element : list) { reverse = reverse.cons(element); } return reverse; } } class functions { public static <T> Curried2<PersistentList<T>, T, PersistentList<T>> cons() { return Segment.functions.cons(); } public static <T> Function0<PersistentList<T>> emptyPersistentList(Class<T> type) { return emptyPersistentList(); } public static <T> Function0<PersistentList<T>> emptyPersistentList() { return returns(PersistentList.constructors.<T>empty()); } public static <T> Function1<PersistentList<T>, PersistentList<T>> cons(T t) { return Segment.functions.cons(t); } public static <T> Function1<PersistentList<T>, PersistentList<T>> tail() { return PersistentList<T>::tail; } public static <T> Function1<PersistentList<T>, PersistentList<T>> tail(Class<T> aClass) { return tail(); } public static <T> Function1<PersistentList<T>, Option<T>> headOption(Class<T> aClass) { return headOption(); } public static <T> Function1<PersistentList<T>, Option<T>> headOption() { return PersistentList<T>::headOption; } } }