Skip to content

Commit e0f69dc

Browse files
izeigermanjbgi
authored andcommitted
Fix a recursive trampoline call in the Eval Defer implementation (functionaljava#329)
1 parent 98294fc commit e0f69dc

File tree

2 files changed

+15
-8
lines changed

2 files changed

+15
-8
lines changed

core/src/main/java/fj/data/Eval.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private static final class DeferEval<A> extends TrampolineEval<A> {
232232

233233
@Override
234234
protected final Trampoline<A> trampoline() {
235-
return memo._1().asTrampoline().trampoline();
235+
return Trampoline.suspend(P.lazy(() -> memo._1().asTrampoline().trampoline()));
236236
}
237237
}
238238
}

core/src/test/java/fj/data/EvalTest.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package fj.data;
22

33
import fj.F0;
4+
import fj.F2;
45
import org.junit.Assert;
56
import org.junit.Test;
67

8+
import java.util.Iterator;
9+
710
public class EvalTest {
811

912
@Test
@@ -42,15 +45,19 @@ public void testAlways() {
4245
@Test
4346
public void testDefer() {
4447
// Make sure that a recursive computation is actually stack-safe.
45-
Assert.assertEquals(even(200000).value(), "done");
46-
}
47-
48-
private static Eval<String> even(int n) {
49-
return Eval.now(n <= 0).flatMap(b -> b ? Eval.now("done") : Eval.defer(() -> odd(n - 1)));
48+
int targetValue = 200000;
49+
Iterator<Integer> it = Enumerator.intEnumerator.toStream(0).iterator();
50+
Eval<Boolean> result = foldRight(it, (v, acc) -> v == targetValue ? Eval.now(true) : acc, false);
51+
Assert.assertTrue(result.value());
5052
}
5153

52-
private static Eval<String> odd(int n) {
53-
return Eval.defer(() -> even(n - 1));
54+
private static <A, T> Eval<A> foldRight(Iterator<T> iterator,
55+
F2<T, Eval<A>, Eval<A>> f,
56+
A zero) {
57+
if (!iterator.hasNext()) {
58+
return Eval.now(zero);
59+
}
60+
return f.f(iterator.next(), Eval.defer(() -> foldRight(iterator, f, zero)));
5461
}
5562

5663
private static class InvocationTrackingF<A> implements F0<A> {

0 commit comments

Comments
 (0)