/* package whatever; // don't place package name! */
import java.util.ArrayList;
import java.util.function.BiFunction;
import java.util.function.Supplier;
class Ideone {
public static void main
(String[] args
) { final var fibs = fibs();
System.
out.
println(Lazy.
forceList(Lazy.
take(10, fibs
))); }
private static List<Integer> fibs() {
final var cell = new Cell<List<Integer>>();
cell.value = Lazy.cons(
() -> 0,
() -> Lazy.cons(
() -> 1,
() -> Lazy.
zip(Integer::sum, cell.
value, cell.
value.
tail()))); return cell.value;
}
}
final class Cell<T> {
T value;
}
final class Promise<T> {
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 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 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;
}
public static <T> List<T> take(int n, List<T> xs) {
if (n <= 0) {
return nil();
}
if (xs == nil()) {
return nil();
}
return cons(xs::head, () -> take(n - 1, xs.tail()));
}
public static <A, B, R> List<R> zip(BiFunction<A, B, R> f, List<A> xs, List<B> ys) {
if (xs == nil()) {
return nil();
}
if (ys == nil()) {
return nil();
}
return cons(
() -> f.apply(xs.head(), ys.head()),
() -> zip(f, xs.tail(), ys.tail()));
}
public static <T> ArrayList<T> forceList(List<T> xs) {
final var list = new ArrayList<T>();
for (var it = xs; it != nil(); it = it.tail()) {
list.add(it.head());
}
return list;
}
@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() {
}
}
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuZnVuY3Rpb24uQmlGdW5jdGlvbjsKaW1wb3J0IGphdmEudXRpbC5mdW5jdGlvbi5TdXBwbGllcjsKCmNsYXNzIElkZW9uZSB7CgogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewogICAgICAgIGZpbmFsIHZhciBmaWJzID0gZmlicygpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihMYXp5LmZvcmNlTGlzdChMYXp5LnRha2UoMTAsIGZpYnMpKSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgTGlzdDxJbnRlZ2VyPiBmaWJzKCkgewogICAgICAgIGZpbmFsIHZhciBjZWxsID0gbmV3IENlbGw8TGlzdDxJbnRlZ2VyPj4oKTsKICAgICAgICBjZWxsLnZhbHVlID0gTGF6eS5jb25zKAogICAgICAgICAgICAgICAgKCkgLT4gMCwKICAgICAgICAgICAgICAgICgpIC0+IExhenkuY29ucygKICAgICAgICAgICAgICAgICAgICAgICAgKCkgLT4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgKCkgLT4gTGF6eS56aXAoSW50ZWdlcjo6c3VtLCBjZWxsLnZhbHVlLCBjZWxsLnZhbHVlLnRhaWwoKSkpKTsKICAgICAgICByZXR1cm4gY2VsbC52YWx1ZTsKICAgIH0KfQoKZmluYWwgY2xhc3MgQ2VsbDxUPiB7CgogICAgVCB2YWx1ZTsKfQoKZmluYWwgY2xhc3MgUHJvbWlzZTxUPiB7CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgT2JqZWN0IHVuZGVmaW5lZCA9IG5ldyBPYmplY3QoKTsKCiAgICBwcml2YXRlIGZpbmFsIFN1cHBsaWVyPFQ+IGRlbGF5ZWRFeHByZXNzaW9uOwoKICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJ1bmNoZWNrZWQiKQogICAgcHJpdmF0ZSBUIHZhbHVlID0gKFQpIHVuZGVmaW5lZDsKCiAgICBQcm9taXNlKFN1cHBsaWVyPFQ+IGV4cHIpIHsKICAgICAgICB0aGlzLmRlbGF5ZWRFeHByZXNzaW9uID0gZXhwcjsKICAgIH0KCiAgICBwdWJsaWMgVCBmb3JjZSgpIHsKICAgICAgICBpZiAodmFsdWUgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhbHVlID0gZGVsYXllZEV4cHJlc3Npb24uZ2V0KCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KfQoKZmluYWwgY2xhc3MgTGlzdDxUPiB7CgogICAgc3RhdGljIGZpbmFsIExpc3Q8Pz4gTklMID0gbmV3IExpc3Q8PihudWxsLCBudWxsKTsKCiAgICBwcml2YXRlIGZpbmFsIFByb21pc2U8VD4gaGVhZDsKICAgIHByaXZhdGUgZmluYWwgUHJvbWlzZTxMaXN0PFQ+PiB0YWlsOwoKICAgIExpc3QoUHJvbWlzZTxUPiBoZWFkLCBQcm9taXNlPExpc3Q8VD4+IHRhaWwpIHsKICAgICAgICB0aGlzLmhlYWQgPSBoZWFkOwogICAgICAgIHRoaXMudGFpbCA9IHRhaWw7CiAgICB9CgogICAgcHVibGljIFQgaGVhZCgpIHsKICAgICAgICByZXR1cm4gaGVhZC5mb3JjZSgpOwogICAgfQoKICAgIHB1YmxpYyBMaXN0PFQ+IHRhaWwoKSB7CiAgICAgICAgcmV0dXJuIHRhaWwuZm9yY2UoKTsKICAgIH0KfQoKZmluYWwgY2xhc3MgTGF6eSB7CgogICAgcHVibGljIHN0YXRpYyA8VD4gUHJvbWlzZTxUPiBkZWxheShTdXBwbGllcjxUPiBleHByKSB7CiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPD4oZXhwcik7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyA8VD4gTGlzdDxUPiBjb25zKFN1cHBsaWVyPFQ+IGhlYWRFeHByLCBTdXBwbGllcjxMaXN0PFQ+PiB0YWlsRXhwcikgewogICAgICAgIHJldHVybiBuZXcgTGlzdDw+KG5ldyBQcm9taXNlPD4oaGVhZEV4cHIpLCBuZXcgUHJvbWlzZTw+KHRhaWxFeHByKSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyA8VD4gTGlzdDxUPiBuaWwoKSB7CiAgICAgICAgQFN1cHByZXNzV2FybmluZ3MoInVuY2hlY2tlZCIpCiAgICAgICAgdmFyIG5pbCA9IChMaXN0PFQ+KSBMaXN0Lk5JTDsKICAgICAgICByZXR1cm4gbmlsOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgPFQ+IExpc3Q8VD4gdGFrZShpbnQgbiwgTGlzdDxUPiB4cykgewogICAgICAgIGlmIChuIDw9IDApIHsKICAgICAgICAgICAgcmV0dXJuIG5pbCgpOwogICAgICAgIH0KICAgICAgICBpZiAoeHMgPT0gbmlsKCkpIHsKICAgICAgICAgICAgcmV0dXJuIG5pbCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY29ucyh4czo6aGVhZCwgKCkgLT4gdGFrZShuIC0gMSwgeHMudGFpbCgpKSk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyA8QSwgQiwgUj4gTGlzdDxSPiB6aXAoQmlGdW5jdGlvbjxBLCBCLCBSPiBmLCBMaXN0PEE+IHhzLCBMaXN0PEI+IHlzKSB7CiAgICAgICAgaWYgKHhzID09IG5pbCgpKSB7CiAgICAgICAgICAgIHJldHVybiBuaWwoKTsKICAgICAgICB9CiAgICAgICAgaWYgKHlzID09IG5pbCgpKSB7CiAgICAgICAgICAgIHJldHVybiBuaWwoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbnMoCiAgICAgICAgICAgICAgICAoKSAtPiBmLmFwcGx5KHhzLmhlYWQoKSwgeXMuaGVhZCgpKSwKICAgICAgICAgICAgICAgICgpIC0+IHppcChmLCB4cy50YWlsKCksIHlzLnRhaWwoKSkpOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgPFQ+IEFycmF5TGlzdDxUPiBmb3JjZUxpc3QoTGlzdDxUPiB4cykgewogICAgICAgIGZpbmFsIHZhciBsaXN0ID0gbmV3IEFycmF5TGlzdDxUPigpOwogICAgICAgIGZvciAodmFyIGl0ID0geHM7IGl0ICE9IG5pbCgpOyBpdCA9IGl0LnRhaWwoKSkgewogICAgICAgICAgICBsaXN0LmFkZChpdC5oZWFkKCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbGlzdDsKICAgIH0KCiAgICBAU2FmZVZhcmFyZ3MKICAgIHB1YmxpYyBzdGF0aWMgPFQ+IExpc3Q8VD4gbGlzdChTdXBwbGllcjxUPi4uLiB2YWx1ZXMpIHsKICAgICAgICBpZiAodmFsdWVzID09IG51bGwgfHwgdmFsdWVzLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgICAgIHJldHVybiBuaWwoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGxpc3QodmFsdWVzLCAwKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyA8VD4gTGlzdDxUPiBsaXN0KFN1cHBsaWVyPFQ+W10gdmFsdWVzLCBpbnQgaGVhZEN1cnNvcikgewogICAgICAgIGlmIChoZWFkQ3Vyc29yID09IHZhbHVlcy5sZW5ndGgpIHsKICAgICAgICAgICAgcmV0dXJuIG5pbCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IExpc3Q8PihuZXcgUHJvbWlzZTw+KHZhbHVlc1toZWFkQ3Vyc29yXSksIG5ldyBQcm9taXNlPD4oKCkgLT4gbGlzdCh2YWx1ZXMsIGhlYWRDdXJzb3IrMSkpKTsKICAgIH0KCiAgICBwcml2YXRlIExhenkoKSB7CiAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKCJ1dGlsaXR5IGNsYXNzIik7CiAgICB9Cn0K