fork download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import java.util.ArrayList;
  4. import java.util.function.BiFunction;
  5. import java.util.function.Supplier;
  6.  
  7. class Ideone {
  8.  
  9. public static void main(String[] args) {
  10. System.out.println(Lazy.forceList(Lazy.take(10, fibs())));
  11. }
  12.  
  13. private static List<Integer> fibs() {
  14. return Lazy.cons(
  15. () -> 0,
  16. () -> Lazy.cons(
  17. () -> 1,
  18. () -> Lazy.zip(Integer::sum, fibs(), fibs().tail())));
  19. }
  20. }
  21.  
  22. final class Promise<T> {
  23.  
  24. private static final Object undefined = new Object();
  25.  
  26. private final Supplier<T> delayedExpression;
  27.  
  28. @SuppressWarnings("unchecked")
  29. private T value = (T) undefined;
  30.  
  31. Promise(Supplier<T> expr) {
  32. this.delayedExpression = expr;
  33. }
  34.  
  35. public T force() {
  36. if (value == undefined) {
  37. value = delayedExpression.get();
  38. }
  39. return value;
  40. }
  41. }
  42.  
  43. final class List<T> {
  44.  
  45. static final List<?> NIL = new List<>(null, null);
  46.  
  47. private final Promise<T> head;
  48. private final Promise<List<T>> tail;
  49.  
  50. List(Promise<T> head, Promise<List<T>> tail) {
  51. this.head = head;
  52. this.tail = tail;
  53. }
  54.  
  55. public T head() {
  56. return head.force();
  57. }
  58.  
  59. public List<T> tail() {
  60. return tail.force();
  61. }
  62. }
  63.  
  64. final class Lazy {
  65.  
  66. public static <T> Promise<T> delay(Supplier<T> expr) {
  67. return new Promise<>(expr);
  68. }
  69.  
  70. public static <T> List<T> cons(Supplier<T> headExpr, Supplier<List<T>> tailExpr) {
  71. return new List<>(new Promise<>(headExpr), new Promise<>(tailExpr));
  72. }
  73.  
  74. public static <T> List<T> nil() {
  75. @SuppressWarnings("unchecked")
  76. var nil = (List<T>) List.NIL;
  77. return nil;
  78. }
  79.  
  80. public static <T> List<T> take(int n, List<T> xs) {
  81. if (n <= 0) {
  82. return nil();
  83. }
  84. if (xs == nil()) {
  85. return nil();
  86. }
  87. return cons(xs::head, () -> take(n - 1, xs.tail()));
  88. }
  89.  
  90. public static <A, B, R> List<R> zip(BiFunction<A, B, R> f, List<A> xs, List<B> ys) {
  91. if (xs == nil()) {
  92. return nil();
  93. }
  94. if (ys == nil()) {
  95. return nil();
  96. }
  97. return cons(
  98. () -> f.apply(xs.head(), ys.head()),
  99. () -> zip(f, xs.tail(), ys.tail()));
  100. }
  101.  
  102. public static <T> ArrayList<T> forceList(List<T> xs) {
  103. final var list = new ArrayList<T>();
  104. for (var it = xs; it != nil(); it = it.tail()) {
  105. list.add(it.head());
  106. }
  107. return list;
  108. }
  109.  
  110. @SafeVarargs
  111. public static <T> List<T> list(Supplier<T>... values) {
  112. if (values == null || values.length == 0) {
  113. return nil();
  114. }
  115. return list(values, 0);
  116. }
  117.  
  118. private static <T> List<T> list(Supplier<T>[] values, int headCursor) {
  119. if (headCursor == values.length) {
  120. return nil();
  121. }
  122. return new List<>(new Promise<>(values[headCursor]), new Promise<>(() -> list(values, headCursor+1)));
  123. }
  124.  
  125. private Lazy() {
  126. throw new UnsupportedOperationException("utility class");
  127. }
  128. }
  129.  
Success #stdin #stdout 0.1s 47820KB
stdin
Standard input is empty
stdout
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]