MemoizingContext extends ForwardingEvalContext { public static EvalContext composeWith(EvalContext baseContext) { return new MemoizingContext(baseContext); } private  MemoizingContext(EvalContext baseContext); static EvalContext composeWith(EvalContext baseContext); @SuppressWarnings("unchecked") @Override Value<T> evaluateInternal(Task<T> task, EvalContext context);  }
@Test public void deDuplicatesSameTasks() throws Exception { Task<Integer> count = Task.named("Count").ofType(Integer.class) .process(() -> counter.incrementAndGet()); Task<Integer> sum = Task.named("Sum").ofType(Integer.class) .input(() -> count) .input(() -> count) .input(() -> count) .process((a, b, c) -> a + b + c); AwaitValue<Integer> await = new AwaitValue<>(); context.evaluate(sum).consume(await); assertThat(evalAndGet(sum), is(3)); assertThat(counter.get(), is(1)); context = MemoizingContext.composeWith(sync()); assertThat(evalAndGet(count), is(2)); assertThat(evalAndGet(count), is(2)); assertThat(counter.get(), is(2)); }