// // Scaled - a scalable editor extensible via JVM languages // http://github.com/scaled/scaled/blob/master/LICENSE package scaled; import java.util.Iterator; import java.util.NoSuchElementException; /** * A simple functional list class, built from cons cells as God and John McCarthy intended. */ public abstract class List implements Iterable { /** Returns the empty list. */ public static List nil () { @SuppressWarnings("unchecked") List nil = (List)NIL; return nil; } /** Creates a list that contains {@code value}. */ public static List apply (A value) { return cons(value, nil()); } /** Creates a list that contains {@code [a, b]}. */ public static List apply (A a, A b) { return cons(a, cons(b, nil())); } /** Creates a list that contains {@code [a, b, c]}. */ public static List apply (A a, A b, A c) { return cons(a, cons(b, cons(c, nil()))); } /** Creates a list that contains {@code values}. */ @SafeVarargs public static List apply (A... values) { List list = nil(); for (int ii = values.length-1; ii >= 0; ii -= 1) list = list.cons(values[ii]); return list; } /** Returns a new list with {@code elem} consed onto its head. */ public static List cons (B head, List tail) { @SuppressWarnings("unchecked") List casted = (List)tail; return new Cons(head, casted); } // ----- List API --------------------------------------------- /** Returns the size of this list. NOTE: this is an O(n) operation. */ public int size () { int size = 0; for (List list = this, nil = nil(); list != nil; list = list.tail()) { size += 1; } return size; } /** * Returns the head of this list. * @throws NoSuchElementException if called on the {@code nil} list. */ public abstract E head (); /** * Returns the tail of this list. * @throws NoSuchElementException if called on the {@code nil} list. */ public abstract List tail (); /** * Returns a new list with {@code elem} consed onto its head. Note: due to limitations of Java's * type system, this method is invariant. Use the static {@code List.cons} if you need the proper * contravariance. */ public List cons (E elem) { return new Cons(elem, this); } /** * Returns an iterator over this list. Note that {@link Iterator#remove} is not supported. */ public Iterator iterator () { return new Iterator() { private List cur; @Override public boolean hasNext() { return cur != nil(); } @Override public E next () { List cur = this.cur; this.cur = cur.tail(); return cur.head(); } @Override public void remove () { throw new UnsupportedOperationException(); } }; } // ----- List impl --------------------------------------------- private static final Nil NIL = new Nil(); private static class Nil extends List { @Override public Object head () { throw new NoSuchElementException("nil.head()"); } @Override public List tail () { throw new NoSuchElementException("nil.tail()"); } }; private static class Cons extends List { @Override public E head () { return head; } @Override public List tail () { return tail; } private Cons (E head, List tail) { if (tail == null) throw new IllegalArgumentException("List tail must not be null."); this.head = head; this.tail = tail; } private final E head; private final List tail; } }