From 3b28d379d404b042c8e60cd84d7a44821792ea36 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Wed, 30 Mar 2016 09:45:01 -0400 Subject: Fix latent bug in LazyHolder. See comment in the constructor of LazyHolderSupplier for details. --- .../main/java/bjc/utils/data/lazy/LazyHolder.java | 42 +++++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'BJC-Utils2/src/main/java') diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java index 6321cc2..ddf3cfc 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java @@ -20,6 +20,33 @@ import bjc.utils.funcdata.FunctionalList; * The type of the data being held */ public class LazyHolder implements IHolder { + private final class LazyHolderSupplier + implements Supplier { + private FunctionalList> pendingActions; + private Function f; + + public LazyHolderSupplier(FunctionalList> actons, + Function f) { + // Resolve latent bug I just realized. After a map, adding new + // actions to the original holder could've resulted in changes + // to all unactualized mapped values from that holder + pendingActions = actons.clone(); + + this.f = f; + } + + @Override + public NewT get() { + if (held == null) { + return pendingActions.reduceAux(heldSrc.get(), + Function::apply, f::apply); + } else { + return pendingActions.reduceAux(held, + Function::apply, f::apply); + } + } + } + /** * List of queued actions to be performed on realized values */ @@ -60,27 +87,23 @@ public class LazyHolder implements IHolder { @Override public void doWith(Consumer f) { transform((val) -> { + // Do the action with the value f.accept(val); + // Return the untransformed value return val; }); } @Override public IHolder map(Function f) { - return new LazyHolder<>(() -> { - if (held == null) { - return actions.reduceAux(heldSrc.get(), - Function::apply, f::apply); - } else { - return actions.reduceAux(held, Function::apply, - f::apply); - } - }); + // Don't actually map until we need to + return new LazyHolder<>(new LazyHolderSupplier<>(actions, f)); } @Override public IHolder transform(Function f) { + // Queue the transform until we need to apply it actions.add(f); return this; @@ -93,6 +116,7 @@ public class LazyHolder implements IHolder { held = heldSrc.get(); } + // Apply all pending transforms actions.forEach((act) -> held = act.apply(held)); return f.apply(held); -- cgit v1.2.3