
com.thejohnfreeman.lazy.Lazy Maven / Gradle / Ivy
Show all versions of lazy Show documentation
package com.thejohnfreeman.lazy;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.thejohnfreeman.function.Function3;
import com.thejohnfreeman.function.Function4;
import com.thejohnfreeman.function.Function5;
import com.thejohnfreeman.function.Function6;
/**
* A lazy value with dependencies.
*
*
* A lazy value is stateful. Before it is forced, it can return its
* dependencies, but not its value. After it is forced, it can return its value,
* but might not be able to return its (former) dependencies.
*
*
* A lazy value cannot be forced until all of its dependencies are forced.
* An iterative algorithm for forcing a directed acyclic graph of lazy values
* is provided as the default implementation of {@link #force()}. It is the
* recommended interface for forcing evaluation.
*
*
* Note: In generic implementing types from this package, the value type is
* always the first type parameter, unlike functional interfaces, where the
* result type is always the last type parameter.
*/
@SuppressWarnings("PMD.TooManyMethods")
public interface Lazy
{
/**
* Returns whether this value has been forced yet.
*
* @return {@code true} iff this value has been successfully forced
*/
boolean isForced();
/**
* Returns an immutable list of this value's dependencies.
*
* @return an immutable list of this value's dependencies
* @throws IllegalStateException if {@code isForced()}
*/
Iterable extends Lazy>> getDependencies() throws IllegalStateException;
/**
* Evaluates and returns this value. May only be called once. Assumes all
* of its dependencies are forced. Generally, you should call
* {@link #force()} instead.
*
* @return the value
* @throws IllegalStateException
* if any dependencies are unforced, or if {@code isForced()}
* @see #force()
*/
T forceThis() throws IllegalStateException;
/**
* Evaluates and returns this value.
*
* @return the value
* @throws IllegalStateException
* if any transitive dependencies cannot be evaluated
*/
default T force()
throws IllegalStateException
{
return Force.force(this);
}
/**
* Returns this value. May not be called unless {@code isForced()}.
*
* @return the value
* @throws IllegalStateException if {@code !isForced()}
* @see #force()
*/
T getValue() throws IllegalStateException;
default String toStringUnforced(final String name) {
return "() -> " + name;
}
static LateBound delay() {
return LateBound.of();
}
static TaggableLazy delay(final T value) {
return Constant.of(value);
}
static TaggableLazy delay(
final Lazy a, final Function func)
{
return Thunk1.of(a, func);
}
static TaggableLazy delay(
final Lazy a, final Lazy b, final BiFunction func)
{
return Thunk2.of(a, b, func);
}
static TaggableLazy delay(
final Lazy a, final Lazy b, final Lazy c,
final Function3 func)
{
return Thunk3.of(a, b, c, func);
}
static TaggableLazy delay(
final Lazy a, final Lazy b, final Lazy c, final Lazy d,
final Function4 func)
{
return Thunk4.of(a, b, c, d, func);
}
static TaggableLazy delay(
final Lazy a, final Lazy b, final Lazy c, final Lazy d,
final Lazy e,
final Function5 func)
{
return Thunk5.of(a, b, c, d, e, func);
}
static TaggableLazy delay(
final Lazy a, final Lazy b, final Lazy c, final Lazy d,
final Lazy e, final Lazy f,
final Function6 func)
{
return Thunk6.of(a, b, c, d, e, f, func);
}
static TaggableLazy delay(
final Collection extends Lazy extends E>> lazies,
final Function super List, T> func)
{
return CollectionThunk.of(lazies, func);
}
static TaggableLazy> sequence(
final Collection extends Lazy extends T>> lazies)
{
return CollectionThunk.sequence(lazies);
}
}