/* package whatever; // don't place package name! */

import java.util.function.Supplier;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone {
	
	public static void main (String[] args) throws java.lang.Exception {
		var ll = Lazy.list( () -> print(1), () -> print(2), () -> print(3) );
        ll.tail().head();
	}
	
	private static Unit print(Object o) {
        System.out.println(o);
        return Unit.UNIT;
    }
}

final class Lazy {

    public static <T> Promise<T> delay(Supplier<T> expr) {
        return new Promise<>(expr);
    }

    public static <T> List<T> cons(Supplier<T> headExpr, Supplier<List<T>> tailExpr) {
        return new List<>(new Promise<>(headExpr), new Promise<>(tailExpr));
    }

    public static <T> List<T> nil() {
        @SuppressWarnings("unchecked")
        var nil = (List<T>) List.NIL;
        return nil;
    }

    @SafeVarargs
    public static <T> List<T> list(Supplier<T>... values) {
        if (values == null || values.length == 0) {
            return nil();
        }
        return list(values, 0);
    }

    private static <T> List<T> list(Supplier<T>[] values, int headCursor) {
        if (headCursor == values.length) {
            return nil();
        }
        return new List<>(new Promise<>(values[headCursor]), new Promise<>(() -> list(values, headCursor+1)));
    }

    private Lazy() {
        throw new UnsupportedOperationException("utility class");
    }
}

final class List<T> {

    static final List<?> NIL = new List<>(null, null);

    private final Promise<T> head;
    private final Promise<List<T>> tail;

    List(Promise<T> head, Promise<List<T>>tail) {
        this.head = head;
        this.tail = tail;
    }

    public T head() {
        return head.force();
    }

    public List<T> tail() {
        return tail.force();
    }
}

final class Promise<T> {

    private static final Object undefined = new Object();

    private final Supplier<T> delayedExpression;

    @SuppressWarnings("unchecked")
    private T value = (T) undefined;

    Promise(Supplier<T> expr) {
        this.delayedExpression = expr;
    }

    public T force() {
        if (value == undefined) {
            value = delayedExpression.get();
        }
        return value;
    }
}

final class Unit {
    
    public static final Unit UNIT = new Unit();
    
    private Unit() {}
}
