All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.organicdesign.fp.LazyRef Maven / Gradle / Ivy

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*") + ")"; }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy