package scotch.runtime;
/**
* A thunk representing a suspended state of computation (i.e. lazy evaluation).
*
* <p>Read <a href="http://en.wikipedia.org/wiki/Thunk">here</a> for more information on thunks.</p>
*
* @param <A> The type of the value to be returned from the Thunk.
*/
public abstract class Thunk<A> implements Callable<A> {
/**
* The value after it has been evaluated to normal form.
*/
private volatile A value;
/**
* Evaluates the thunk down to normal form.
*
* <p><a href="http://stackoverflow.com/questions/6872898/haskell-what-is-weak-head-normal-form">Read here</a> for
* explanation of what normal form is.</p>
*
* @return The normalized value.
*/
@SuppressWarnings("unchecked")
@Override
public A call() {
if (value == null) {
synchronized (this) {
if (value == null) {
value = evaluate();
while (value instanceof Callable) {
if (value instanceof Applicable) {
break;
}
value = ((Callable<A>) value).call();
}
}
}
}
return value;
}
/**
* Evaluates the value.
*
* @return The evaluated value.
*/
protected abstract A evaluate();
}