# Source: Future.js

    "use strict";
    /**
     * A future is a thing that occurs at some point in time with a value.
     * It can be understood as a pair consisting of the time the future
     * occurs and its associated value. It is quite like a JavaScript
     * promise.
     */
    class Future {
        constructor() {
            this.listeners = [];
        }
        listen(o) {
            if (this.occured !== true) {
                this.listeners.push(o);
            }
            else {
                o.push(this.value);
            }
        }
        subscribe(f) {
            return new Subscribtion(f, this);
        }
        resolve(val) {
            this.occured = true;
            this.value = val;
            const listeners = this.listeners;
            for (let i = 0, l = listeners.length; i < l; ++i) {
                listeners[i].push(val);
            }
        }
        // A future is a functor, when the future occurs we can feed is't
        // result through the mapping function
        map(f) {
            return new MapFuture(f, this);
        }
        mapTo(b) {
            return new MapToFuture(b, this);
        }
        // A future is an applicative. `of` gives a future that has always
        // occured at all points in time.
        static of(b) {
            return new PureFuture(b);
        }
        of(b) {
            return new PureFuture(b);
        }
        static lift(f, ...args) {
            return f.length === 1 ? new MapFuture(f, args[0])
                : new LiftFuture(f, args);
        }
        // A future is a monad. Once the first future occurs `chain` passes
        // its value through the chain function and the future it returns is
        // the one returned by `chain`.
        chain(f) {
            return new ChainFuture(f, this);
        }
    }
    exports.Future = Future;
    class MapFuture extends Future {
        constructor(f, parent) {
            super();
            this.f = f;
            this.parent = parent;
            parent.listen(this);
        }
        push(val) {
            this.resolve(this.f(val));
        }
    }
    class MapToFuture extends Future {
        constructor(value, parent) {
            super();
            this.value = value;
            this.parent = parent;
            parent.listen(this);
        }
        push(_) {
            this.resolve(this.value);
        }
    }
    class PureFuture extends Future {
        constructor(value) {
            super();
            this.value = value;
            this.occured = true;
        }
        push(_) {
            throw new Error("A PureFuture should never be pushed to.");
        }
    }
    class LiftFuture extends Future {
        constructor(f, futures) {
            super();
            this.f = f;
            this.futures = futures;
            this.delivered = 0;
            const l = this.dependencies = futures.length;
            for (let i = 0; i < l; ++i) {
                futures[i].listen(this);
            }
        }
        push(_) {
            const l = this.dependencies;
            if (++this.delivered === l) {
                // All the dependencies have occurred.
                for (let i = 0; i < l; ++i) {
                    this.futures[i] = this.futures[i].value;
                }
                this.resolve(this.f.apply(undefined, this.futures));
            }
        }
    }
    class ChainFuture extends Future {
        constructor(f, parent) {
            super();
            this.f = f;
            this.parent = parent;
            this.parentOccurred = false;
            parent.listen(this);
        }
        push(val) {
            if (this.parentOccurred === false) {
                // The first future occured. We can now call `f` with it's value
                // and listen to the future it returns.
                this.parentOccurred = true;
                const newFuture = this.f(val);
                newFuture.listen(this);
            }
            else {
                this.resolve(val);
            }
        }
    }
    // I Sink is a producer that one can imperatively resolve.
    class Sink extends Future {
        push(val) {
            throw new Error("A sink should never be pushed to.");
        }
    }
    function sink() {
        return new Sink();
    }
    exports.sink = sink;
    // A subscribtion is a consumer that performs a side
    class Subscribtion {
        constructor(f, parent) {
            this.f = f;
            this.parent = parent;
            parent.listen(this);
        }
        push(a) {
            this.f(a); // let `f` perform its side-effect.
        }
    }
    function fromPromise(p) {
        const future = sink();
        p.then(future.resolve.bind(future));
        return future;
    }
    exports.fromPromise = fromPromise;
    /**
     * Create a future from a pushing behavior. The future occurs when the
     * behavior pushes it's next value. Constructing a BehaviorFuture is
     * impure and should not be done direcly.
     * @private
     */
    class BehaviorFuture extends Future {
        constructor(b) {
            super();
            this.b = b;
            b.addListener(this);
        }
        push(a) {
            this.b.unlisten(this);
            this.resolve(a);
        }
    }
    exports.BehaviorFuture = BehaviorFuture;
    exports.of = Future.of;
    exports.lift = Future.lift;
    //# sourceMappingURL=Future.js.map