Skip to content

Commit

Permalink
Add JavaDoc for Eval
Browse files Browse the repository at this point in the history
  • Loading branch information
angelo-streetcontxt committed Jun 4, 2016
1 parent 9278f1b commit 16354ae
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 86 deletions.
12 changes: 4 additions & 8 deletions src/main/java/ca/genovese/coffeecats/data/eval/Always.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
/**
* /**
* Construct a lazy Eval<A> instance.
* <p>
* This type can be used for "lazy" values. In some sense it is
* <p>This type can be used for "lazy" values. In some sense it is
* equivalent to using a Supplier value.
* <p>
* This type will evaluate the computation every time the value is
* <p>This type will evaluate the computation every time the value is
* required. It should be avoided except when laziness is required and
* caching must be avoided. Generally, prefer Later.
*
Expand All @@ -30,8 +28,7 @@ final class Always<A> implements Eval<A> {

/**
* Evaluate the computation and return an A value.
* <p>
* For lazy instances (Later, Always), any necessary computation
* <p>For lazy instances (Later, Always), any necessary computation
* will be performed at this point. For eager instances (Now), a
* value will be immediately returned.
*
Expand All @@ -45,8 +42,7 @@ public A value() {
/**
* Ensure that the result of the computation (if any) will be
* memoized.
* <p>
* Practically, this means that when called on an Always&lt;A&gt; a
* <p>Practically, this means that when called on an Always&lt;A&gt; a
* Later&lt;A&gt; with an equivalent computation will be returned.
*
* @return A new, memoizing, Eval that is equivalent to the current Eval
Expand Down
28 changes: 14 additions & 14 deletions src/main/java/ca/genovese/coffeecats/data/eval/Compute.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,29 @@

/**
* Compute is a type of Eval&lt;A&gt; that is used to chain computations
* involving .map and .flatMap. Along with Eval#flatMap it
* involving map() and flatMap(). Along with Eval#flatMap it
* implements the trampoline that guarantees stack-safety.
* <p>
* Users should not instantiate Compute instances
* <p>Users should not instantiate Compute instances
* themselves. Instead, they will be automatically created when
* needed.
* <p>
* Unlike a traditional trampoline, the internal workings of the
* <p>Unlike a traditional trampoline, the internal workings of the
* trampoline are not exposed. This allows a slightly more efficient
* implementation of the .value method.
*
* @param <A> The type returned by this Eval
*/
final class Compute<A> implements Eval<A> {
/**
* The function which returns the initial Eval.
*/
private final Supplier<Eval> start;
/**
* The function to apply to start's value to calculate the value of this eval.
*/
private final Function run;

/**
* Creates a new Eval, based on an existing Eval and a function
* Creates a new Eval, based on an existing Eval and a function.
*
* @param start The Eval from which this Eval's computation is started
* @param run The function to apply to the start Eval's value to calculate this Eval
Expand All @@ -37,13 +41,11 @@ final class Compute<A> implements Eval<A> {
/**
* Lazily perform a computation based on an Eval&lt;A&gt;, using the
* function `f` to produce an Eval&lt;B&gt; given an A.
* <p>
* This call is stack-safe -- many .flatMap calls may be chained
* <p>This call is stack-safe -- many .flatMap calls may be chained
* without consumed additional stack during evaluation. It is also
* written to avoid left-association problems, so that repeated
* calls to .flatMap will be efficiently applied.
* <p>
* Computation performed in f is always lazy, even when called on an
* <p>Computation performed in f is always lazy, even when called on an
* eager (Now) instance.
*
* @param f the function to apply to the result of the current computation
Expand All @@ -60,8 +62,7 @@ public <B> Eval<B> flatMap(final Function<A, Eval<B>> f) {
/**
* Ensure that the result of the computation (if any) will be
* memoized.
* <p>
* Practically, this means that when called on an Always&lt;A&gt; a
* <p>Practically, this means that when called on an Always&lt;A&gt; a
* Later&lt;A&gt; with an equivalent computation will be returned.
*
* @return A new, memoizing, Eval that is equivalent to the current Eval
Expand All @@ -73,8 +74,7 @@ public Eval<A> memoize() {

/**
* Evaluate the computation and return an A value.
* <p>
* For lazy instances (Later, Always), any necessary computation
* <p>For lazy instances (Later, Always), any necessary computation
* will be performed at this point. For eager instances (Now), a
* value will be immediately returned.
*
Expand Down
50 changes: 20 additions & 30 deletions src/main/java/ca/genovese/coffeecats/data/eval/Eval.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,24 @@

/**
* Eval is a monad which controls evaluation.
* <p>
* This type wraps a value (or a computation that produces a value)
* <p>This type wraps a value (or a computation that produces a value)
* and can produce it on command via the `.value()` method.
* <p>
* There are three basic evaluation strategies:
* <p>
* - Now: evaluated immediately
* - Later: evaluated once when value is needed
* - Always: evaluated every time value is needed
* <p>
* The Later and Always are both lazy strategies while Now is eager.
* <p>There are three basic evaluation strategies:
* <ul>
* <li>Now: evaluated immediately</li>
* <li>- Later: evaluated once when value is needed</li>
* <li>- Always: evaluated every time value is needed</li>
* </ul>
* <p>The Later and Always are both lazy strategies while Now is eager.
* Later and Always are distinguished from each other only by
* memoization: once evaluated Later will save the value to be returned
* immediately if it is needed again. Always will run its computation
* every time.
* <p>
* Eval supports stack-safe lazy computation via the .map and .flatMap
* <p>Eval supports stack-safe lazy computation via the .map and .flatMap
* methods, which use an internal trampoline to avoid stack overflows.
* Computation done within .map and .flatMap is always done lazily,
* even when applied to a Now instance.
* <p>
* Use .map and .flatMap to chain computation, and use .value
* <p>Use .map and .flatMap to chain computation, and use .value
* to get the result when needed. It is not good style to create
* Eval instances whose computation involves calling .value on another
* Eval instance -- this can defeat the trampolining and lead to stack
Expand All @@ -41,7 +37,7 @@ public interface Eval<A> extends Serializable, Kind<Eval, A> {
/**
* Return a new Computation which calculates it's value strictly. Basically equivalent to a variable.
*
* @param a The value to use as the result of this Computation
* @param a The value to use as the result of this Computation
* @param <A> The type returned by the new Eval
* @return The new Eval
*/
Expand All @@ -53,7 +49,7 @@ static <A> Eval<A> now(A a) {
* Return a new Computation which calculates it's value once, strictly.
* Basically equivalent to a variable in java or a var or val in scala.
*
* @param a The function to use to calculate the result of this Computation
* @param a The function to use to calculate the result of this Computation
* @param <A> The type returned by the new Eval
* @return The new Eval
*/
Expand All @@ -65,7 +61,7 @@ static <A> Eval<A> now(Supplier<A> a) {
* Return a new Computation which calculates it's value once, lazily.
* Basically equivalent to a lazy val in scala.
*
* @param a The function to use to calculate the result of this Computation
* @param a The function to use to calculate the result of this Computation
* @param <A> The type returned by the new Eval
* @return The new Eval
*/
Expand All @@ -77,7 +73,7 @@ static <A> Eval<A> later(Supplier<A> a) {
* Return a new Computation which calculates it's value on each invocation.
* Basically equivalent to a method call.
*
* @param a The function to use to calculate the result of this Computation
* @param a The function to use to calculate the result of this Computation
* @param <A> The type returned by the new Eval
* @return The new Eval
*/
Expand All @@ -87,8 +83,7 @@ static <A> Eval<A> always(Supplier<A> a) {

/**
* Evaluate the computation and return an A value.
* <p>
* For lazy instances (Later, Always), any necessary computation
* <p>For lazy instances (Later, Always), any necessary computation
* will be performed at this point. For eager instances (Now), a
* value will be immediately returned.
*
Expand All @@ -99,11 +94,9 @@ static <A> Eval<A> always(Supplier<A> a) {
/**
* Transform an Eval&lt;A&gt; into an Eval&lt;B&gt; given the transformation
* function `f`.
* <p>
* This call is stack-safe -- many .map calls may be chained without
* <p>This call is stack-safe -- many .map calls may be chained without
* consumed additional stack during evaluation.
* <p>
* Computation performed in f is always lazy, even when called on an
* <p>Computation performed in f is always lazy, even when called on an
* eager (Now) instance.
*
* @param f the function to apply to the result of the current computation
Expand All @@ -117,13 +110,11 @@ default <B> Eval<B> map(final Function<A, B> f) {
/**
* Lazily perform a computation based on an Eval&lt;A&gt;, using the
* function `f` to produce an Eval&lt;B&gt; given an A.
* <p>
* This call is stack-safe -- many .flatMap calls may be chained
* <p>This call is stack-safe -- many .flatMap calls may be chained
* without consumed additional stack during evaluation. It is also
* written to avoid left-association problems, so that repeated
* calls to .flatMap will be efficiently applied.
* <p>
* Computation performed in f is always lazy, even when called on an
* <p>Computation performed in f is always lazy, even when called on an
* eager (Now) instance.
*
* @param f the function to apply to the result of the current computation
Expand All @@ -137,8 +128,7 @@ default <B> Eval<B> flatMap(final Function<A, Eval<B>> f) {
/**
* Ensure that the result of the computation (if any) will be
* memoized.
* <p>
* Practically, this means that when called on an Always&lt;A&gt; a
* <p>Practically, this means that when called on an Always&lt;A&gt; a
* Later&lt;A&gt; with an equivalent computation will be returned.
*
* @return A new, memoizing, Eval that is equivalent to the current Eval
Expand Down
21 changes: 11 additions & 10 deletions src/main/java/ca/genovese/coffeecats/data/eval/Later.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@

/**
* Construct a lazy Eval&lt;A&gt; instance.
* <p>
* This type should be used for most "lazy" values. In some sense it
* <p>This type should be used for most "lazy" values. In some sense it
* is equivalent to using a lazy val.
* <p>
* When caching is not required or desired (e.g. if the value produced
* <p>When caching is not required or desired (e.g. if the value produced
* may be large) prefer Always. When there is no computation
* necessary, prefer Now.
* <p>
* Once Later has been evaluated, the closure (and any values captured
* <p>Once Later has been evaluated, the closure (and any values captured
* by the closure) will not be retained, and will be available for
* garbage collection.
*
* @param <A> The type returned by this Eval
*/
final class Later<A> implements Eval<A> {
/**
* The function to use in calculating the value of this Eval.
*/
private Supplier<A> thunk;
/**
* The value of this Eval if it has already been computed, or None if it has not.
*/
private Option<A> value = Option.none();

/**
Expand All @@ -36,8 +39,7 @@ final class Later<A> implements Eval<A> {

/**
* Evaluate the computation and return an A value.
* <p>
* For lazy instances (Later, Always), any necessary computation
* <p>For lazy instances (Later, Always), any necessary computation
* will be performed at this point. For eager instances (Now), a
* value will be immediately returned.
*
Expand All @@ -55,8 +57,7 @@ public A value() {
/**
* Ensure that the result of the computation (if any) will be
* memoized.
* <p>
* Practically, this means that when called on an Always&lt;A&gt; a
* <p>Practically, this means that when called on an Always&lt;A&gt; a
* Later&lt;A&gt; with an equivalent computation will be returned.
*
* @return A new, memoizing, Eval that is equivalent to the current Eval
Expand Down
17 changes: 8 additions & 9 deletions src/main/java/ca/genovese/coffeecats/data/eval/Now.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@

/**
* Construct an eager Eval&lt;A&gt; instance.
* <p>
* In some sense it is equivalent to using a val.
* <p>
* This type should be used when an A value is already in hand, or
* <p>In some sense it is equivalent to using a val.
* <p>This type should be used when an A value is already in hand, or
* when the computation to produce an A value is pure and very fast.
*
* @param <A> The type returned by this Eval
*/
final class Now<A> implements Eval<A> {
/**
* The value of this Eval.
*/
private final A value;

/**
* Return a new Computation which calculates it's value strictly. Basically equivalent to a variable.
*
* @param a The value to use as the result of this Computation
* @param value The value to use as the result of this Computation
*/
Now(final A value) {
this.value = value;
}

/**
* Evaluate the computation and return an A value.
* <p>
* For lazy instances (Later, Always), any necessary computation
* <p>For lazy instances (Later, Always), any necessary computation
* will be performed at this point. For eager instances (Now), a
* value will be immediately returned.
*
Expand All @@ -39,8 +39,7 @@ public A value() {
/**
* Ensure that the result of the computation (if any) will be
* memoized.
* <p>
* Practically, this means that when called on an Always&lt;A&gt; a
* <p>Practically, this means that when called on an Always&lt;A&gt; a
* Later&lt;A&gt; with an equivalent computation will be returned.
*
* @return A new, memoizing, Eval that is equivalent to the current Eval
Expand Down
26 changes: 11 additions & 15 deletions src/main/java/ca/genovese/coffeecats/data/eval/package-info.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
/**
* Eval is a monad which controls evaluation.
* <p>
* This type wraps a value (or a computation that produces a value)
* <p>This type wraps a value (or a computation that produces a value)
* and can produce it on command via the `.value()` method.
* <p>
* There are three basic evaluation strategies:
* <p>
* - Now: evaluated immediately
* - Later: evaluated once when value is needed
* - Always: evaluated every time value is needed
* <p>
* The Later and Always are both lazy strategies while Now is eager.
* <p>There are three basic evaluation strategies:
* <ul>
* <li>Now: evaluated immediately</li>
* <li>- Later: evaluated once when value is needed</li>
* <li>- Always: evaluated every time value is needed</li>
* </ul>
* <p>The Later and Always are both lazy strategies while Now is eager.
* Later and Always are distinguished from each other only by
* memoization: once evaluated Later will save the value to be returned
* immediately if it is needed again. Always will run its computation
* every time.
* <p>
* Eval supports stack-safe lazy computation via the .map and .flatMap
* <p>Eval supports stack-safe lazy computation via the .map and .flatMap
* methods, which use an internal trampoline to avoid stack overflows.
* Computation done within .map and .flatMap is always done lazily,
* even when applied to a Now instance.
* <p>
* Use .map and .flatMap to chain computation, and use .value
* <p>Use .map and .flatMap to chain computation, and use .value
* to get the result when needed. It is not good style to create
* Eval instances whose computation involves calling .value on another
* Eval instance -- this can defeat the trampolining and lead to stack
* overflows.
*/
package ca.genovese.coffeecats.data.eval;
package ca.genovese.coffeecats.data.eval;

0 comments on commit 16354ae

Please sign in to comment.