org.organicdesign.fp.LazyRef Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of UncleJim Show documentation
Show all versions of UncleJim Show documentation
Immutable Clojure collections and a Transformation abstraction for Java 8+, immutably, type-safely, and with good performance. Name will change to "Paguro" in November 2016.
package org.organicdesign.fp;
import org.organicdesign.fp.function.Function0;
/**
Lazily initialize a value (and free the initialization resources) on the first call to get().
Subsequent calls to get() cheaply return the previously initialized value. This class is thread-safe if the producer
function and the value it produces are pure and free from side effects.
*/
public class LazyRef {
private Function0 producer;
private T value;
private LazyRef(Function0 p) { producer = p; }
/**
* Use this function to produce a value on the first call to get(). Delete the pointer to this function when that
* first call completes, but remember the value to return with all subsequent calls to get().
* @param producer will produce the desired value when called.
* @param
* @return
*/
public static LazyRef of(Function0 producer) {
if (producer == null) {
throw new IllegalArgumentException("The producer function cannot be null (the value it returns can)");
}
return new LazyRef<>(producer);
}
/**
The first call to this method initializes the value this class wraps and releases the initialization resources.
Subsequent calls return the precomputed value.
@return the same value every time it is called.
*/
// This whole method is synchronized on the advice of Goetz2006 p. 347
public synchronized T get() {
// Have we produced our value yet?
if (producer != null) {
// produce our value.
value = producer.apply();
// Delete the producer to 1. mark the work done and 2. free resources.
producer = null;
}
// We're clear to return the lazily computed value.
return value;
}
// I don't like this because it's not referentially transparent.
// public boolean isRealizedYet() { return producer == null; }
// I don't like this because it's not referentially transparent, but it could be helpful for testing.
/**
Useful for debugging, but not referentially transparent (sometimes returns LazyRef(*not-computed-yet*),
sometimes shows the value that was computed).
@return a string describing this LazyRef and showing whether or not its value has been computed yet.
*/
public String toString() { return "LazyRef(" + ((producer == null) ? value : "*not-computed-yet*") + ")"; }
}