Socket
Socket
Sign inDemoInstall

fluture

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fluture - npm Package Compare versions

Comparing version 3.1.1 to 4.0.0

1687

fluture.js

@@ -14,10 +14,10 @@ //// ____ _ _

if(module && typeof module.exports !== 'undefined'){
module.exports = f(require('inspect-f'));
module.exports = f(require('inspect-f'), require('sanctuary-type-classes'));
}
else{
global.Fluture = f(global.inspectf);
global.Fluture = f(global.inspectf, global.sanctuaryTypeClasses);
}
}(/*istanbul ignore next*/(global || window || this), function(inspectf){
}(/*istanbul ignore next*/(global || window || this), function(inspectf, Z){

@@ -45,3 +45,3 @@ 'use strict';

function isFuture(m){
return (m instanceof FutureClass) || Boolean(m) && m['@@type'] === TYPEOF_FUTURE;
return m instanceof Future || Boolean(m) && m['@@type'] === TYPEOF_FUTURE;
}

@@ -81,30 +81,4 @@

//A small string representing a value, but not containing the whole value.
const preview = x =>
typeof x === 'string'
? JSON.stringify(x)
: Array.isArray(x)
? `[Array: ${x.length}]`
: typeof x === 'function'
? typeof x.name === 'string' && x.name.length > 0
? `[Function: ${x.name}]`
: /*istanbul ignore next*/ '[Function]' //Only for older JS engines.
: x && typeof x === 'object'
? `[Object: ${Object.keys(x).map(String).join(', ')}]`
: String(x);
//A show function to provide a slightly more meaningful representation of values.
const show = x =>
typeof x === 'string'
? preview(x)
: Array.isArray(x)
? `[${x.map(preview).join(', ')}]`
: x && (typeof x.toString === 'function')
? x.toString === Object.prototype.toString
? `{${Object.keys(x).reduce((o, k) => o.concat(`${preview(k)}: ${preview(x[k])}`), []).join(', ')}}`
: x.toString()
: preview(x);
const show = Z.toString;
const noop = function noop(){};
const call = function call(f){f()};
const padf = (sf, s) => s.replace(/^/gm, sf).replace(sf, '');

@@ -138,6 +112,40 @@ const showf = f => padf(' ', inspectf(2, f));

////////////
// Errors //
////////////
//Creates a dispatcher for a nullary method.
function createNullaryDispatcher(method){
return function nullaryDispatch(m){
if(m && typeof m[method] === 'function') return m[method]();
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
};
}
//Creates a dispatcher for a unary method.
function createUnaryDispatcher(method){
return function unaryDispatch(a, m){
if(arguments.length === 1) return unaryPartial(unaryDispatch, a);
if(m && typeof m[method] === 'function') return m[method](a);
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
};
}
//Creates a dispatcher for a binary method.
function createBinaryDispatcher(method){
return function binaryDispatch(a, b, m){
if(arguments.length === 1) return unaryPartial(binaryDispatch, a);
if(arguments.length === 2) return binaryPartial(binaryDispatch, a, b);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 2, `have a "${method}" method`, m);
};
}
//Creates a dispatcher for a binary method, but takes the object first rather than last.
function createInvertedBinaryDispatcher(method){
return function invertedBinaryDispatch(m, a, b){
if(arguments.length === 1) return unaryPartial(invertedBinaryDispatch, m);
if(arguments.length === 2) return binaryPartial(invertedBinaryDispatch, m, a);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 0, `have a "${method}" method`, m);
};
}
//Creates an error about an invalid argument.
function error$invalidArgument(it, at, expected, actual){

@@ -149,2 +157,3 @@ throw new TypeError(

//Creates an error message about a method being called with an invalid context.
function error$invalidContext(it, actual){

@@ -157,12 +166,355 @@ throw new TypeError(

function check$Future(fork){
if(!isFunction(fork)) error$invalidArgument('Future', 0, 'be a function', fork);
////////////////
// Base class //
////////////////
function Future(f){
if(!isFunction(f)) error$invalidArgument('Future', 0, 'be a function', f);
return new SafeFuture(f);
}
function check$fork(it, rej, res){
if(!isFuture(it)) error$invalidContext('Future#fork', it);
function Future$of(x){
return new FutureOf(x);
}
function Future$chainRec(f, init){
if(arguments.length === 1) return unaryPartial(Future$chainRec, f);
if(!isFunction(f)) error$invalidArgument('Future.chainRec', 0, 'be a function', f);
return new ChainRec(f, init);
}
Future.prototype['@@type'] = TYPEOF_FUTURE;
Future.prototype._f = null;
Future.prototype.extractLeft = function Future$extractLeft(){ return []; }
Future.prototype.extractRight = function Future$extractRight(){ return []; }
Future.prototype.of = Future$of;
Future.prototype.ap = function Future$ap(m){
if(!isFuture(this)) error$invalidContext('Future#ap', this);
if(!isFuture(m)) error$invalidArgument('Future#ap', 0, 'be a Future', m);
return new FutureAp(this, m);
};
Future.prototype.map = function Future$map(f){
if(!isFuture(this)) error$invalidContext('Future#map', this);
if(!isFunction(f)) error$invalidArgument('Future#map', 0, 'be a function', f);
return new FutureMap(this, f);
};
Future.prototype.bimap = function Future$bimap(f, g){
if(!isFuture(this)) error$invalidContext('Future#bimap', this);
if(!isFunction(f)) error$invalidArgument('Future#bimap', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#bimap', 1, 'be a function', g);
return new FutureBimap(this, f, g);
};
Future.prototype.chain = function Future$chain(f){
if(!isFuture(this)) error$invalidContext('Future#chain', this);
if(!isFunction(f)) error$invalidArgument('Future#chain', 0, 'be a function', f);
return new FutureChain(this, f);
};
Future.prototype.chainRej = function Future$chainRej(f){
if(!isFuture(this)) error$invalidContext('Future.chainRej', this);
if(!isFunction(f)) error$invalidArgument('Future.chainRej', 0, 'a function', f);
return new FutureChainRej(this, f);
};
Future.prototype.mapRej = function Future$mapRej(f){
if(!isFuture(this)) error$invalidContext('Future#mapRej', this);
if(!isFunction(f)) error$invalidArgument('Future#mapRej', 0, 'be a function', f);
return new FutureMapRej(this, f);
};
Future.prototype.swap = function Future$swap(){
if(!isFuture(this)) error$invalidContext('Future#swap', this);
return new FutureSwap(this);
};
Future.prototype.race = function Future$race(m){
if(!isFuture(this)) error$invalidContext('Future#race', this);
if(!isFuture(m)) error$invalidArgument('Future#race', 0, 'be a Future', m);
return new FutureRace(this, m);
};
Future.prototype.and = function Future$and(m){
if(!isFuture(this)) error$invalidContext('Future#and', this);
if(!isFuture(m)) error$invalidArgument('Future#and', 0, 'be a Future', m);
return new FutureAnd(this, m);
};
Future.prototype.or = function Future$or(m){
if(!isFuture(this)) error$invalidContext('Future#or', this);
if(!isFuture(m)) error$invalidArgument('Future#or', 0, 'be a Future', m);
return new FutureOr(this, m);
};
Future.prototype.both = function Future$both(m){
if(!isFuture(this)) error$invalidContext('Future#both', this);
if(!isFuture(m)) error$invalidArgument('Future#both', 0, 'be a Future', m);
return new FutureBoth(this, m);
};
Future.prototype.fold = function Future$fold(f, g){
if(!isFuture(this)) error$invalidContext('Future#fold', this);
if(!isFunction(f)) error$invalidArgument('Future#fold', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#fold', 1, 'be a function', g);
return new FutureFold(this, f, g);
};
Future.prototype.hook = function Future$hook(dispose, consume){
if(!isFuture(this)) error$invalidContext('Future#hook', this);
if(!isFunction(dispose)) error$invalidArgument('Future#hook', 0, 'be a function', dispose);
if(!isFunction(consume)) error$invalidArgument('Future#hook', 1, 'be a function', consume);
return new FutureHook(this, dispose, consume);
};
Future.prototype.finally = function Future$finally(m){
if(!isFuture(this)) error$invalidContext('Future#finally', this);
if(!isFuture(m)) error$invalidArgument('Future#finally', 0, 'be a Future', m);
return new FutureFinally(this, m);
};
Future.prototype.cache = function Future$cache(){
if(!isFuture(this)) error$invalidContext('Future#cache', this);
return new CachedFuture(this);
};
Future.prototype.fork = function Future$fork(rej, res){
if(!isFuture(this)) error$invalidContext('Future#fork', this);
if(!isFunction(rej)) error$invalidArgument('Future#fork', 0, 'be a function', rej);
if(!isFunction(res)) error$invalidArgument('Future#fork', 1, 'be a function', res);
return this._f(rej, res);
};
Future.prototype.inspect = function Future$inspect(){
return this.toString();
};
Future.prototype.value = function Future$value(f){
if(!isFuture(this)) error$invalidContext('Future#value', this);
if(!isFunction(f)) error$invalidArgument('Future#value', 0, 'be a function', f);
return this._f(function Future$value$rej(e){
throw new Error(
`Future#value was called on a rejected Future\n Actual: Future.reject(${show(e)})`
);
}, f);
};
Future.prototype.promise = function Future$promise(){
if(!isFuture(this)) error$invalidContext('Future#promise', this);
const _this = this;
return new Promise(function Future$promise$do(resolve, reject){
_this._f(reject, resolve);
});
};
Future.of = Future$of;
Future.chainRec = Future$chainRec;
Future.Future = Future;
Future.isFuture = isFuture;
Future.isForkable = isForkable;
function ap$mval(mval, mfunc){
if(!Z.Apply.test(mfunc)) error$invalidArgument('Future.ap', 1, 'be an Apply', mfunc);
return Z.ap(mval, mfunc);
}
Future.ap = function ap(mval, mfunc){
if(!Z.Apply.test(mval)) error$invalidArgument('Future.ap', 0, 'be an Apply', mval);
if(arguments.length === 1) return unaryPartial(ap$mval, mval);
return ap$mval(mval, mfunc);
}
function map$mapper(mapper, m){
if(!Z.Functor.test(m)) error$invalidArgument('Future.map', 1, 'be a Functor', m);
return Z.map(mapper, m);
}
Future.map = function map(mapper, m){
if(!isFunction(mapper)) error$invalidArgument('Future.map', 0, 'be a Function', mapper);
if(arguments.length === 1) return unaryPartial(map$mapper, mapper);
return map$mapper(mapper, m);
}
function bimap$lmapper$rmapper(lmapper, rmapper, m){
if(!Z.Bifunctor.test(m)) error$invalidArgument('Future.bimap', 2, 'be a Bifunctor', m);
return Z.bimap(lmapper, rmapper, m);
}
function bimap$lmapper(lmapper, rmapper, m){
if(!isFunction(rmapper)) error$invalidArgument('Future.bimap', 1, 'be a Function', rmapper);
if(arguments.length === 2) return binaryPartial(bimap$lmapper$rmapper, lmapper, rmapper);
return bimap$lmapper$rmapper(lmapper, rmapper, m);
}
Future.bimap = function bimap(lmapper, rmapper, m){
if(!isFunction(lmapper)) error$invalidArgument('Future.bimap', 0, 'be a Function', lmapper);
if(arguments.length === 1) return unaryPartial(bimap$lmapper, lmapper);
return bimap$lmapper(lmapper, rmapper, m);
}
function chain$chainer(chainer, m){
if(!Z.Chain.test(m)) error$invalidArgument('Future.chain', 1, 'be a Chain', m);
return Z.chain(chainer, m);
}
Future.chain = function chain(chainer, m){
if(!isFunction(chainer)) error$invalidArgument('Future.chain', 0, 'be a Function', chainer);
if(arguments.length === 1) return unaryPartial(chain$chainer, chainer);
return chain$chainer(chainer, m);
}
function and$left(left, right){
if(!isFuture(right)) error$invalidArgument('Future.and', 1, 'be a Future', right);
return new FutureAnd(left, right);
}
Future.and = function and(left, right){
if(!isFuture(left)) error$invalidArgument('Future.and', 0, 'be a Future', left);
if(arguments.length === 1) return unaryPartial(and$left, left);
return and$left(left, right);
}
function both$left(left, right){
if(!isFuture(right)) error$invalidArgument('Future.both', 1, 'be a Future', right);
return new FutureBoth(left, right);
}
Future.both = function both(left, right){
if(!isFuture(left)) error$invalidArgument('Future.both', 0, 'be a Future', left);
if(arguments.length === 1) return unaryPartial(both$left, left);
return both$left(left, right);
}
Future.reject = function Future$reject(x){
return new FutureReject(x);
};
function Future$after$n(n, x){
return new FutureAfter(n, x);
}
Future.after = function Future$after(n, x){
if(!isPositiveInteger(n)) error$invalidArgument('Future.after', 0, 'be a positive integer', n);
if(arguments.length === 1) return unaryPartial(Future$after$n, n);
return Future$after$n(n, x);
};
function rejectAfter$time(time, reason){
return new FutureRejectAfter(time, reason);
}
Future.rejectAfter = function rejectAfter(time, reason){
if(!isPositiveInteger(time)) error$invalidArgument(
'Future.rejectAfter', 0, 'be a positive integer', time
);
if(arguments.length === 1) return unaryPartial(rejectAfter$time, time);
return rejectAfter$time(time, reason);
}
Future.cast = function Future$cast(m){
if(!isForkable(m)) error$invalidArgument('Future.cast', 0, 'be a Forkable', m);
return new FutureCast(m);
};
Future.try = function Future$try(f){
if(!isFunction(f)) error$invalidArgument('Future.try', 0, 'be a function', f);
return new FutureTry(f);
};
Future.encase = function Future$encase(f, x){
if(arguments.length === 1) return unaryPartial(Future$encase, f);
if(!isFunction(f)) error$invalidArgument('Future.encase', 0, 'be a function', f);
return new FutureEncase(f, x);
};
Future.encase2 = function Future$encase2(f, x, y){
switch(arguments.length){
case 1: return unaryPartial(Future$encase2, f);
case 2: return binaryPartial(Future$encase2, f, x);
default:
if(!isFunction(f)) error$invalidArgument('Future.encase2', 0, 'be a function', f);
if(!isBinary(f)) error$invalidArgument('Future.encase2', 0, 'take two arguments', f);
return new FutureEncase(f, x, y);
}
};
Future.encase3 = function Future$encase3(f, x, y, z){
switch(arguments.length){
case 1: return unaryPartial(Future$encase3, f);
case 2: return binaryPartial(Future$encase3, f, x);
case 3: return ternaryPartial(Future$encase3, f, x, y);
default:
if(!isFunction(f)) error$invalidArgument('Future.encase3', 0, 'be a function', f);
if(!isTernary(f)) error$invalidArgument('Future.encase3', 0, 'take three arguments', f);
return new FutureEncase(f, x, y, z);
}
};
Future.node = function Future$node(f){
if(!isFunction(f)) error$invalidArgument('Future.node', 0, 'be a function', f);
return new FutureNode(f);
};
Future.parallel = function Future$parallel(i, ms){
if(arguments.length === 1) return unaryPartial(Future$parallel, i);
if(!isPositiveInteger(i)) error$invalidArgument('Future.parallel', 0, 'be a positive integer', i);
if(!Array.isArray(ms)) error$invalidArgument('Future.parallel', 1, 'be an array', ms);
return new FutureParallel(i, ms);
};
Future.do = function Future$do(f){
if(!isFunction(f)) error$invalidArgument('Future.do', 0, 'be a function', f);
return new FutureDo(f);
};
Future.chainRej = createUnaryDispatcher('chainRej');
Future.mapRej = createUnaryDispatcher('mapRej');
Future.swap = createNullaryDispatcher('swap');
Future.fork = createBinaryDispatcher('fork');
Future.race = createUnaryDispatcher('race');
Future.or = createUnaryDispatcher('or');
Future.fold = createBinaryDispatcher('fold');
Future.hook = createInvertedBinaryDispatcher('hook');
Future.finally = createUnaryDispatcher('finally');
Future.value = createUnaryDispatcher('value');
Future.promise = createNullaryDispatcher('promise');
Future.cache = createNullaryDispatcher('cache');
Future.extractLeft = createNullaryDispatcher('extractLeft');
Future.extractRight = createNullaryDispatcher('extractRight');
//Utilities.
Future.util = {
Next,
Done,
isForkable,
isFuture,
isFunction,
isBinary,
isTernary,
isPositiveInteger,
isObject,
isIterator,
isIteration,
padf,
showf,
fid,
unaryPartial,
binaryPartial,
ternaryPartial
};
//Fantasy-Land compatibility.
Future[FL.of] = Future.of;
Future[FL.chainRec] = Future$chainRec;
Future.prototype[FL.ap] = Future.prototype.ap;
Future.prototype[FL.map] = Future.prototype.map;
Future.prototype[FL.bimap] = Future.prototype.bimap;
Future.prototype[FL.chain] = Future.prototype.chain;
/////////////////
// Sub classes //
/////////////////
function check$fork$f(f, c){

@@ -175,11 +527,39 @@ if(!(f === undefined || (isFunction(f) && f.length === 0))) throw new TypeError(

function check$chain(it, f){
if(!isFuture(it)) error$invalidContext('Future#chain', it);
if(!isFunction(f)) error$invalidArgument('Future#chain', 0, 'be a function', f);
function SafeFuture(computation){
this._computation = computation;
}
function check$chainRec(f){
if(!isFunction(f)) error$invalidArgument('Future.chainRec', 0, 'be a function', f);
SafeFuture.prototype = Object.create(Future.prototype);
SafeFuture.prototype._f = function SafeFuture$fork(rej, res){
let open = true;
const f = this._computation(function SafeFuture$fork$rej(x){
if(open){
open = false;
rej(x);
}
}, function SafeFuture$fork$res(x){
if(open){
open = false;
res(x);
}
});
check$fork$f(f, this._computation);
return function SafeFuture$fork$cancel(){
open && f && f();
open = false;
};
}
SafeFuture.prototype.toString = function SafeFuture$toString(){
return `Future(${showf(this._computation)})`;
}
//----------
//data Timing = Undetermined | Synchronous | Asynchronous
const Undetermined = 0;
const Synchronous = 1;
const Asynchronous = 2;
function check$chainRec$f(m, f, i, x){

@@ -208,150 +588,282 @@ if(!isFuture(m)) throw new TypeError(

function check$recur(it, f){
if(!isFuture(it)) error$invalidContext('Future#recur', it);
if(!isFunction(f)) error$invalidArgument('Future#recur', 0, 'be a function', f);
function ChainRec(iterate, init){
this._iterate = iterate;
this._init = init;
}
function check$chain$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#chain expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
ChainRec.prototype = Object.create(Future.prototype);
ChainRec.prototype._f = function ChainRec$fork(rej, res){
const _this = this;
let cancel = noop, i = 0;
(function Future$chainRec$recur(state){
let timing = Undetermined;
function Future$chainRec$res(it){
check$chainRec$it(it, i);
i = i + 1;
if(timing === Undetermined){
timing = Synchronous;
state = it;
}else{
Future$chainRec$recur(it);
}
}
while(!state.done){
timing = Undetermined;
const m = _this._iterate(Next, Done, state.value);
check$chainRec$f(m, _this._iterate, i, state.value);
cancel = m._f(rej, Future$chainRec$res);
if(timing !== Synchronous){
timing = Asynchronous;
return;
}
}
res(state.value);
}(Next(_this._init)));
return function Future$chainRec$cancel(){ cancel() };
}
function check$recur$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#recur expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
ChainRec.prototype.toString = function ChainRec$toString(){
return `Future.chainRec(${showf(this._iterate)}, ${show(this._init)})`;
}
function check$chainRej(it, f){
if(!isFuture(it)) error$invalidContext('Future.chainRej', it);
if(!isFunction(f)) error$invalidArgument('Future.chainRej', 0, 'a function', f);
//----------
//data State = Cold | Pending | Rejected | Resolved
const Cold = 0;
const Pending = 1;
const Rejected = 2;
const Resolved = 3;
function Queued(rej, res){
this[Rejected] = rej;
this[Resolved] = res;
}
function check$chainRej$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future.chainRej expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
function CachedFuture(pure){
this._pure = pure;
this._cancel = noop;
this._queue = [];
this._queued = 0;
this._value = null;
this._state = Cold;
}
function check$map(it, f){
if(!isFuture(it)) error$invalidContext('Future#map', it);
if(!isFunction(f)) error$invalidArgument('Future#map', 0, 'be a function', f);
CachedFuture.STATE = {
[Cold]: 'cold',
[Pending]: 'pending',
[Rejected]: 'rejected',
[Resolved]: 'resolved'
};
CachedFuture.prototype = Object.create(Future.prototype);
CachedFuture.prototype.extractLeft = function CachedFuture$extractLeft(){
return this._state === Rejected ? [this._value] : [];
}
function check$mapRej(it, f){
if(!isFuture(it)) error$invalidContext('Future#mapRej', it);
if(!isFunction(f)) error$invalidArgument('Future#mapRej', 0, 'be a function', f);
CachedFuture.prototype.extractRight = function CachedFuture$extractRight(){
return this._state === Resolved ? [this._value] : [];
}
function check$bimap(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#bimap', it);
if(!isFunction(f)) error$invalidArgument('Future#bimap', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#bimap', 1, 'be a function', g);
CachedFuture.prototype._addToQueue = function CachedFuture$addToQueue(rej, res){
const _this = this;
if(_this._state > Pending) return noop;
const i = _this._queue.push(new Queued(rej, res)) - 1;
_this._queued = _this._queued + 1;
return function CachedFuture$removeFromQueue(){
if(_this._state > Pending) return;
_this._queue[i] = undefined;
_this._queued = _this._queued - 1;
if(_this._queued === 0) _this.reset();
};
}
function check$ap(it, m){
if(!isFuture(it)) error$invalidContext('Future#ap', it);
if(!isFuture(m)) error$invalidArgument('Future#ap', 0, 'be a Future', m);
CachedFuture.prototype._drainQueue = function CachedFuture$drainQueue(){
if(this._state <= Pending) return;
if(this._queued === 0) return;
const queue = this._queue;
const length = queue.length;
const state = this._state;
const value = this._value;
for(let i = 0; i < length; i++){
queue[i] && queue[i][state](value);
queue[i] = undefined;
}
this._queue = undefined;
this._queued = 0;
}
function check$ap$f(f){
if(!isFunction(f)) throw new TypeError(
'Future#ap expects its first argument to be a Future of a Function'
+ `\n Actual: Future.of(${show(f)})`
CachedFuture.prototype.reject = function CachedFuture$reject(reason){
if(this._state > Pending) return;
this._value = reason;
this._state = Rejected;
this._drainQueue();
}
CachedFuture.prototype.resolve = function CachedFuture$resolve(value){
if(this._state > Pending) return;
this._value = value;
this._state = Resolved;
this._drainQueue();
}
CachedFuture.prototype.run = function CachedFuture$run(){
const _this = this;
if(_this._state > Cold) return;
_this._state = Pending;
_this._cancel = _this._pure._f(
function CachedFuture$fork$rej(x){ _this.reject(x) },
function CachedFuture$fork$res(x){ _this.resolve(x) }
);
}
function check$swap(it){
if(!isFuture(it)) error$invalidContext('Future#swap', it);
CachedFuture.prototype.reset = function CachedFuture$reset(){
if(this._state === Cold) return;
if(this._state > Pending) this._cancel();
this._cancel = noop;
this._queue = [];
this._queued = 0;
this._value = undefined;
this._state = Cold;
}
function check$race(it, m){
if(!isFuture(it)) error$invalidContext('Future#race', it);
if(!isFuture(m)) error$invalidArgument('Future#race', 0, 'be a Future', m);
CachedFuture.prototype.getState = function CachedFuture$getState(){
return CachedFuture.STATE[this._state];
}
function check$or(it, m){
if(!isFuture(it)) error$invalidContext('Future#or', it);
if(!isFuture(m)) error$invalidArgument('Future#or', 0, 'be a Future', m);
CachedFuture.prototype._f = function CachedFuture$fork(rej, res){
const _this = this;
let cancel = noop;
switch(_this._state){
case 1: cancel = _this._addToQueue(rej, res); break;
case 2: rej(_this._value); break;
case 3: res(_this._value); break;
default: cancel = _this._addToQueue(rej, res); _this.run();
}
return cancel;
}
function check$fold(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#fold', it);
if(!isFunction(f)) error$invalidArgument('Future#fold', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#fold', 1, 'be a function', g);
CachedFuture.prototype.inspect = function CachedFuture$inspect(){
const repr = this._state === Resolved
? show(this._value)
: `<${this.getState()}>` + (this._state === Rejected ? ` ${this._value}` : '');
return `CachedFuture({ ${repr} })`;
}
function check$hook(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#hook', it);
if(!isFunction(f)) error$invalidArgument('Future#hook', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#hook', 1, 'be a function', g);
CachedFuture.prototype.toString = function CachedFuture$toString(){
return `${this._pure.toString()}.cache()`;
}
function check$hook$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the first function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
//----------
function FutureOf(value){
this._value = value;
}
function check$hook$g(m, g, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the second function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(g)}\n With: ${show(x)}`
);
FutureOf.prototype = Object.create(Future.prototype);
FutureOf.prototype.extractRight = function FutureOf$extractRight(){
return [this._value];
}
function check$finally(it, m){
if(!isFuture(it)) error$invalidContext('Future#finally', it);
if(!isFuture(m)) error$invalidArgument('Future#finally', 0, 'be a Future', m);
FutureOf.prototype._f = function FutureOf$fork(rej, res){
res(this._value);
return noop;
}
function check$value(it, f){
if(!isFuture(it)) error$invalidContext('Future#value', it);
if(!isFunction(f)) error$invalidArgument('Future#value', 0, 'be a function', f);
FutureOf.prototype.toString = function FutureOf$toString(){
return `Future.of(${show(this._value)})`;
}
function check$promise(it){
if(!isFuture(it)) error$invalidContext('Future#promise', it);
//----------
function FutureReject(reason){
this._reason = reason;
}
function check$cache(it){
if(!isFuture(it)) error$invalidContext('Future#cache', it);
FutureReject.prototype = Object.create(Future.prototype);
FutureReject.prototype.extractLeft = function FutureReject$extractLeft(){
return [this._reason];
}
function check$after(n){
if(typeof n !== 'number') error$invalidArgument('Future.after', 0, 'be a number', n);
FutureReject.prototype._f = function FutureReject$fork(rej){
rej(this._reason);
return noop;
}
function check$cast(m){
if(!isForkable(m)) error$invalidArgument('Future.cast', 0, 'be a Forkable', m);
FutureReject.prototype.toString = function FutureReject$toString(){
return `Future.reject(${show(this._reason)})`;
}
function check$encase(f){
if(!isFunction(f)) error$invalidArgument('Future.encase', 0, 'be a function', f);
//----------
function FutureNode(computation){
this._computation = computation;
}
function check$encase2(f){
if(!isFunction(f)) error$invalidArgument('Future.encase2', 0, 'be a function', f);
if(!isBinary(f)) error$invalidArgument('Future.encase2', 0, 'take two arguments', f);
FutureNode.prototype = Object.create(Future.prototype);
FutureNode.prototype._f = function FutureNode$fork(rej, res){
let open = true;
this._computation(function FutureNode$fork$done(a, b){
if(open){
a ? rej(a) : res(b);
open = false;
}
});
return function FutureNode$fork$cancel(){ open = false };
}
function check$encase3(f){
if(!isFunction(f)) error$invalidArgument('Future.encase3', 0, 'be a function', f);
if(!isTernary(f)) error$invalidArgument('Future.encase3', 0, 'take three arguments', f);
FutureNode.prototype.toString = function FutureNode$toString(){
return `Future.node(${showf(this._computation)})`;
}
function check$node(f){
if(!isFunction(f)) error$invalidArgument('Future.node', 0, 'be a function', f);
//----------
function FutureAfter(time, value){
this._time = time;
this._value = value;
}
function check$parallel(i, ms){
if(!isPositiveInteger(i)) error$invalidArgument('Future.parallel', 0, 'be a positive integer', i);
if(!Array.isArray(ms)) error$invalidArgument('Future.parallel', 1, 'be an array', ms);
FutureAfter.prototype = Object.create(Future.prototype);
FutureAfter.prototype.extractRight = function FutureAfter$extractRight(){
return [this._value];
}
FutureAfter.prototype._f = function FutureAfter$fork(rej, res){
const id = setTimeout(res, this._time, this._value);
return function FutureAfter$fork$cancel(){ clearTimeout(id) };
}
FutureAfter.prototype.toString = function FutureAfter$toString(){
return `Future.after(${show(this._time)}, ${show(this._value)})`;
}
//----------
function FutureRejectAfter(time, reason){
this._time = time;
this._reason = reason;
}
FutureRejectAfter.prototype = Object.create(Future.prototype);
FutureRejectAfter.prototype.extractLeft = function FutureRejectAfter$extractLeft(){
return [this._reason];
}
FutureRejectAfter.prototype._f = function FutureRejectAfter$fork(rej){
const id = setTimeout(rej, this._time, this._reason);
return function FutureRejectAfter$fork$cancel(){ clearTimeout(id) };
}
FutureRejectAfter.prototype.toString = function FutureRejectAfter$toString(){
return `Future.rejectAfter(${show(this._time)}, ${show(this._reason)})`;
}
//----------
function check$parallel$m(m, i){

@@ -364,6 +876,43 @@ if(!isFuture(m)) throw new TypeError(

function check$do(f){
if(!isFunction(f)) error$invalidArgument('Future.do', 0, 'be a function', f);
function FutureParallel$emptyFork(rej, res){
res([]);
}
function FutureParallel(max, futures){
this._futures = futures;
this._length = futures.length;
this._max = Math.min(this._length, max);
if(futures.length === 0) this._f = FutureParallel$emptyFork;
}
FutureParallel.prototype = Object.create(Future.prototype);
FutureParallel.prototype._f = function FutureParallel$fork(rej, res){
const _this = this, cancels = new Array(_this._max), out = new Array(_this._length);
let i = _this._max, ok = 0;
const cancelAll = function Future$parallel$cancel(){
for(let n = 0; n < _this._max; n++) cancels[n] && cancels[n]();
};
const run = function FutureParallel$fork$run(future, j, c){
check$parallel$m(future, j);
cancels[c] = future._f(function Future$parallel$fork$rej(reason){
cancelAll();
rej(reason);
}, function Future$parallel$fork$res(value){
out[j] = value;
ok = ok + 1;
if(i < _this._length) run(_this._futures[i], i++, c);
else if(ok === _this._length) res(out);
});
}
for(let n = 0; n < _this._max; n++) run(_this._futures[n], n, n);
return cancelAll;
}
FutureParallel.prototype.toString = function FutureParallel$toString(){
return `Future.parallel(${show(this._max)}, [${this._futures.map(show).join(', ')}])`;
}
//----------
function check$do$g(g){

@@ -388,539 +937,505 @@ if(!isIterator(g)) error$invalidArgument(

////////////
// Future //
////////////
function FutureDo(generator){
this._generator = generator;
}
function FutureClass(safe, f){
this._f = safe === true ? Future$safeFork : f;
this._raw = f;
FutureDo.prototype = Object.create(Future.prototype);
FutureDo.prototype._f = function FutureDo$fork(rej, res){
const iterator = this._generator();
check$do$g(iterator);
const recurser = new ChainRec(function Future$do$next(next, _, x){
const iteration = iterator.next(x);
check$do$next(iteration);
return iteration.done ? new FutureOf(iteration) : iteration.value.map(next);
}, undefined);
return recurser._f(rej, res);
}
function Future(f){
check$Future(f);
return new FutureClass(true, f);
FutureDo.prototype.toString = function FutureDo$toString(){
return `Future.do(${showf(this._generator)})`;
}
function Future$of(x){
return new FutureClass(false, function Future$of$fork(rej, res){
res(x);
//----------
function FutureCast(forkable){
SafeFuture.call(this, (l, r) => forkable.fork(l, r));
this._forkable = forkable;
}
FutureCast.prototype = Object.create(SafeFuture.prototype);
FutureCast.prototype.toString = function FutureCast$toString(){
return `Future.cast(${show(this._forkable)})`;
}
//----------
function FutureTry(fn){
this._fn = fn;
}
FutureTry.prototype = Object.create(Future.prototype);
FutureTry.prototype._f = function FutureTry$0$fork(rej, res){
let r;
try{ r = this._fn() }catch(e){ rej(e); return noop }
res(r);
return noop;
}
FutureTry.prototype.toString = function FutureTry$toString(){
return `Future.try(${show(this._fn)})`;
}
//----------
function FutureEncase(fn, a, b, c){
this._length = arguments.length - 1;
this._fn = fn;
this._a = a;
this._b = b;
this._c = c;
this._f = FutureEncase.FS[this._length];
}
FutureEncase.FS = {
1: function FutureEncase$1$fork(rej, res){
let r;
try{ r = this._fn(this._a) }catch(e){ rej(e); return noop }
res(r);
return noop;
});
},
2: function FutureEncase$2$fork(rej, res){
let r;
try{ r = this._fn(this._a, this._b) }catch(e){ rej(e); return noop }
res(r);
return noop;
},
3: function FutureEncase$3$fork(rej, res){
let r;
try{ r = this._fn(this._a, this._b, this._c) }catch(e){ rej(e); return noop }
res(r);
return noop;
}
}
function Future$chainRec(f, init){
if(arguments.length === 1) return unaryPartial(Future$chainRec, f);
check$chainRec(f);
return new FutureClass(false, function(rej, res){
let cancel = noop, i = 0;
(function Future$chainRec$recur(state){
let isSync = null;
function Future$chainRec$res(it){
check$chainRec$it(it, i);
i = i + 1;
if(isSync === null){
isSync = true;
state = it;
}else{
Future$chainRec$recur(it);
}
}
while(!state.done){
isSync = null;
const m = f(Next, Done, state.value);
check$chainRec$f(m, f, i, state.value);
cancel = m._f(rej, Future$chainRec$res);
if(isSync === true){
continue;
}else{
isSync = false;
return;
}
}
res(state.value);
}(Next(init)));
return function Future$chainRec$cancel(){ cancel() };
});
FutureEncase.prototype = Object.create(Future.prototype);
FutureEncase.prototype.toString = function FutureEncase$toString(){
const args = [this._a, this._b, this._c].slice(0, this._length).map(show).join(', ');
const name = `encase${this._length > 1 ? this._length : ''}`;
return `Future.${name}(${show(this._fn)}, ${args})`;
}
function Future$fork(rej, res){
check$fork(this, rej, res);
return this._f(rej, res);
//----------
function check$chain$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#chain expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function Future$safeFork(rej, res){
let open = true;
const f = this._raw(function Future$safeFork$rej(x){
if(open){
open = false;
rej(x);
}
}, function Future$safeFork$res(x){
if(open){
open = false;
res(x);
}
});
check$fork$f(f, this._raw);
return function Future$safeFork$cancel(){
open && f && f();
open = false;
};
function FutureChain(parent, chainer){
this._parent = parent;
this._chainer = chainer;
}
function Future$chain(f){
check$chain(this, f);
FutureChain.prototype = Object.create(Future.prototype);
FutureChain.prototype._f = function FutureChain$fork(rej, res){
const _this = this;
return new FutureClass(false, function Future$chain$fork(rej, res){
let cancel;
const r = _this._f(rej, function Future$chain$res(x){
const m = f(x);
check$chain$f(m, f, x);
cancel = m._f(rej, res);
});
return cancel ? cancel : (cancel = r, function Future$chain$cancel(){ cancel() });
let cancel;
const r = _this._parent._f(rej, function FutureChain$fork$res(x){
const m = _this._chainer(x);
check$chain$f(m, _this._chainer, x);
cancel = m._f(rej, res);
});
return cancel || (cancel = r, function FutureChain$fork$cancel(){ cancel() });
}
function Future$recur(f){
check$recur(this, f);
const _this = this;
return new FutureClass(false, function Future$chain$fork(rej, res){
return _this._f(rej, function Future$chain$res(x){
const m = f(x);
check$recur$f(m, f, x);
m._f(rej, res);
});
});
FutureChain.prototype.toString = function FutureChain$toString(){
return `${this._parent.toString()}.chain(${showf(this._chainer)})`;
}
function Future$chainRej(f){
check$chainRej(this, f);
const _this = this;
return new FutureClass(false, function Future$chainRej$fork(rej, res){
let cancel;
const r = _this._f(function Future$chainRej$rej(x){
const m = f(x);
check$chainRej$f(m, f, x);
cancel = m._f(rej, res);
}, res);
return cancel ? cancel : (cancel = r, function Future$chainRej$cancel(){ cancel() });
});
//----------
function check$chainRej$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future.chainRej expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function Future$map(f){
check$map(this, f);
const _this = this;
return new FutureClass(false, function Future$map$fork(rej, res){
return _this._f(rej, function Future$map$res(x){
res(f(x));
});
});
function FutureChainRej(parent, chainer){
this._parent = parent;
this._chainer = chainer;
}
function Future$mapRej(f){
check$mapRej(this, f);
FutureChainRej.prototype = Object.create(Future.prototype);
FutureChainRej.prototype._f = function FutureChainRej$fork(rej, res){
const _this = this;
return new FutureClass(false, function Future$mapRej$fork(rej, res){
return _this._f(function Future$mapRej$rej(x){
rej(f(x));
}, res);
});
let cancel;
const r = _this._parent._f(function FutureChainRej$fork$rej(x){
const m = _this._chainer(x);
check$chainRej$f(m, _this._chainer, x);
cancel = m._f(rej, res);
}, res);
return cancel || (cancel = r, function FutureChainRej$fork$cancel(){ cancel() });
}
function Future$bimap(f, g){
check$bimap(this, f, g);
const _this = this;
return new FutureClass(false, function Future$bimap$fork(rej, res){
return _this._f(function Future$bimap$rej(x){
rej(f(x));
}, function Future$bimap$res(x){
res(g(x));
});
});
FutureChainRej.prototype.toString = function FutureChainRej$toString(){
return `${this._parent.toString()}.chainRej(${showf(this._chainer)})`;
}
function Future$ap(m){
check$ap(this, m);
const _this = this;
return new FutureClass(false, function Future$ap$fork(g, res){
let _f, _x, ok1, ok2, ko;
const rej = x => ko || (ko = 1, g(x));
const c1 = _this._f(rej, function Future$ap$resThis(x){
if(!ok1) return void (ok2 = 1, _x = x)
check$ap$f(_f);
res(_f(x));
});
const c2 = m._f(rej, function Future$ap$resThat(f){
if(!ok2) return void (ok1 = 1, _f = f);
check$ap$f(f);
res(f(_x));
});
return function Future$ap$cancel(){ c1(); c2() };
});
//----------
function FutureMap(parent, mapper){
this._parent = parent;
this._mapper = mapper;
}
function Future$swap(){
check$swap(this);
FutureMap.prototype = Object.create(Future.prototype);
FutureMap.prototype._f = function FutureMap$fork(rej, res){
const _this = this;
return new FutureClass(false, function Future$swap$fork(rej, res){
return _this._f(res, rej);
return _this._parent._f(rej, function FutureMap$fork$res(x){
res(_this._mapper(x));
});
}
function Future$toString(){
return `Future(${this._raw.toString()})`;
FutureMap.prototype.toString = function FutureMap$toString(){
return `${this._parent.toString()}.map(${showf(this._mapper)})`;
}
function Future$race(m){
check$race(this, m);
const _this = this;
return new FutureClass(false, function Future$race$fork(rej, res){
let settled = false, c1 = noop, c2 = noop;
const once = f => a => settled || (settled = true, c1(), c2(), f(a));
c1 = _this._f(once(rej), once(res));
c2 = m._f(once(rej), once(res));
return function Future$race$cancel(){ c1(); c2() };
});
//----------
function FutureMapRej(parent, mapper){
this._parent = parent;
this._mapper = mapper;
}
function Future$or(m){
check$or(this, m);
FutureMapRej.prototype = Object.create(Future.prototype);
FutureMapRej.prototype._f = function FutureMapRej$fork(rej, res){
const _this = this;
return new FutureClass(false, function Future$or$fork(rej, res){
let ok = false, ko = false, val, err;
const c1 = _this._f(
() => ko ? rej(err) : ok ? res(val) : (ko = true),
x => (ok = true, res(x))
);
const c2 = m._f(
e => ok || (ko ? rej(e) : (err = e, ko = true)),
x => ok || (ko ? res(x) : (val = x, ok = true))
);
return function Future$or$cancel(){ c1(); c2() };
});
return _this._parent._f(function FutureMapRej$fork$rej(x){
rej(_this._mapper(x));
}, res);
}
function Future$fold(f, g){
check$fold(this, f, g);
const _this = this;
return new FutureClass(false, function Future$fold$fork(rej, res){
return _this._f(e => res(f(e)), x => res(g(x)));
});
FutureMapRej.prototype.toString = function FutureMapRej$toString(){
return `${this._parent.toString()}.mapRej(${showf(this._mapper)})`;
}
function Future$hook(dispose, consume){
check$hook(this, dispose, consume);
const _this = this;
return new FutureClass(false, function Future$hook$fork(rej, res){
let cancel;
const ret = _this._f(rej, function Future$hook$res(resource){
const m = consume(resource);
check$hook$g(m, consume, resource);
cancel = m._f(e => {
const c = dispose(resource);
check$hook$f(c, dispose, resource);
c._f(rej, _ => rej(e));
}, x => {
const c = dispose(resource);
check$hook$f(c, dispose, resource);
c._f(rej, _ => res(x));
});
});
cancel = cancel || ret;
return function Future$hook$cancel(){ cancel() };
});
//----------
function FutureBimap(parent, lmapper, rmapper){
this._parent = parent;
this._lmapper = lmapper;
this._rmapper = rmapper;
}
function Future$finally(m){
check$finally(this, m);
FutureBimap.prototype = Object.create(Future.prototype);
FutureBimap.prototype._f = function FutureBimap$fork(rej, res){
const _this = this;
return new FutureClass(false, function Future$finally$fork(rej, res){
let cancel;
const r = _this._f(function Future$finally$rej(e){
cancel = m._f(rej, function Future$finally$rej$res(){ rej(e) });
}, function Future$finally$res(x){
cancel = m._f(rej, function Future$finally$res$res(){ res(x) });
});
return cancel ? cancel : (cancel = r, function Future$finally$cancel(){ cancel() });
return _this._parent._f(function FutureBimap$fork$rej(x){
rej(_this._lmapper(x));
}, function FutureBimap$fork$res(x){
res(_this._rmapper(x));
});
}
function Future$value(f){
check$value(this, f);
return this._f(
function Future$value$rej(e){
throw new Error(
`Future#value was called on a rejected Future\n Actual: Future.reject(${show(e)})`
);
},
f
FutureBimap.prototype.toString = function FutureBimap$toString(){
return `${this._parent.toString()}.bimap(${showf(this._lmapper)}, ${showf(this._rmapper)})`;
}
//----------
function check$ap$f(f){
if(!isFunction(f)) throw new TypeError(
'Future#ap expects its first argument to be a Future of a Function'
+ `\n Actual: Future.of(${show(f)})`
);
}
function Future$promise(){
check$promise(this);
const _this = this;
return new Promise(function Future$promise$do(resolve, reject){
_this._f(reject, resolve);
});
function FutureAp(mval, mfunc){
this._mval = mval;
this._mfunc = mfunc;
}
function Future$cache(){
check$cache(this);
FutureAp.prototype = Object.create(Future.prototype);
FutureAp.prototype._f = function FutureAp$fork(rej, res){
const _this = this;
let que = [];
let value, state;
const settleWith = newState => function Future$cache$settle(newValue){
value = newValue; state = newState;
for(let i = 0, l = que.length; i < l; i++){
que[i][state](value);
que[i] = undefined;
}
que = undefined;
};
return new FutureClass(false, function Future$cache$fork(rej, res){
let cancel = noop;
switch(state){
case 1: que.push({2: rej, 3: res}); break;
case 2: rej(value); break;
case 3: res(value); break;
default:
state = 1;
que.push({2: rej, 3: res});
cancel = _this._f(settleWith(2), settleWith(3));
}
return function Future$cache$cancel(){
que = [];
value = undefined;
state = undefined;
cancel();
};
let cancel;
const r = _this._mval._f(rej, function FutureAp$fork$res$x(x){
cancel = _this._mfunc._f(rej, function FutureAp$fork$res$f(f){
check$ap$f(f);
cancel = noop;
res(f(x));
});
});
return cancel || (cancel = r, function FutureAp$fork$cancel(){ cancel() });
}
FutureClass.prototype = Future.prototype = {
'@@type': TYPEOF_FUTURE,
_f: null,
fork: Future$fork,
[FL.of]: Future$of,
of: Future$of,
[FL.chainRec]: Future$chainRec,
[FL.chain]: Future$chain,
chain: Future$chain,
recur: Future$recur,
chainRej: Future$chainRej,
[FL.map]: Future$map,
map: Future$map,
mapRej: Future$mapRej,
[FL.bimap]: Future$bimap,
bimap: Future$bimap,
[FL.ap]: Future$ap,
ap: Future$ap,
swap: Future$swap,
toString: Future$toString,
inspect: Future$toString,
race: Future$race,
or: Future$or,
fold: Future$fold,
hook: Future$hook,
finally: Future$finally,
value: Future$value,
promise: Future$promise,
cache: Future$cache
};
FutureAp.prototype.toString = function FutureAp$toString(){
return `${this._mval.toString()}.ap(${this._mfunc.toString()})`;
}
Future[FL.of] = Future.of = Future$of;
Future[FL.chainRec] = Future.chainRec = Future$chainRec;
Future.Future = Future;
//----------
Future.util = {
Next,
Done,
isForkable,
isFuture,
isFunction,
isBinary,
isTernary,
isPositiveInteger,
isObject,
isIterator,
isIteration,
preview,
show,
padf,
showf,
fid,
unaryPartial,
binaryPartial,
ternaryPartial
};
function FutureSwap(parent){
this._parent = parent;
}
/////////////////
// Dispatchers //
/////////////////
FutureSwap.prototype = Object.create(Future.prototype);
//Creates a dispatcher for a nullary method.
function createNullaryDispatcher(method){
return function nullaryDispatch(m){
if(m && typeof m[method] === 'function') return m[method]();
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
};
FutureSwap.prototype._f = function FutureSwap$fork(rej, res){
return this._parent._f(res, rej);
}
//Creates a dispatcher for a unary method.
function createUnaryDispatcher(method){
return function unaryDispatch(a, m){
if(arguments.length === 1) return unaryPartial(unaryDispatch, a);
if(m && typeof m[method] === 'function') return m[method](a);
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
};
FutureSwap.prototype.toString = function FutureSwap$toString(){
return `${this._parent.toString()}.swap()`;
}
//Creates a dispatcher for a binary method.
function createBinaryDispatcher(method){
return function binaryDispatch(a, b, m){
if(arguments.length === 1) return unaryPartial(binaryDispatch, a);
if(arguments.length === 2) return binaryPartial(binaryDispatch, a, b);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 2, `have a "${method}" method`, m);
};
//----------
function FutureRace(left, right){
this._left = left;
this._right = right;
}
//Creates a dispatcher for a binary method, but takes the object first rather than last.
function createInvertedBinaryDispatcher(method){
return function invertedBinaryDispatch(m, a, b){
if(arguments.length === 1) return unaryPartial(invertedBinaryDispatch, m);
if(arguments.length === 2) return binaryPartial(invertedBinaryDispatch, m, a);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 0, `have a "${method}" method`, m);
};
FutureRace.prototype = Object.create(Future.prototype);
FutureRace.prototype._f = function FutureRace$fork(rej, res){
let cancelled = false, lcancel = noop, rcancel = noop;
const cancel = function FutureRace$fork$cancel(){ cancelled = true; lcancel(); rcancel() };
const reject = function FutureRace$fork$rej(x){ cancel(); rej(x) }
const resolve = function FutureRace$fork$res(x){ cancel(); res(x) }
lcancel = this._left._f(reject, resolve);
cancelled || (rcancel = this._right._f(reject, resolve));
return cancel;
}
Future.chain = createUnaryDispatcher(FL.chain);
Future.recur = createUnaryDispatcher('recur');
Future.chainRej = createUnaryDispatcher('chainRej');
Future.map = createUnaryDispatcher(FL.map);
Future.mapRej = createUnaryDispatcher('mapRej');
Future.bimap = createBinaryDispatcher(FL.bimap);
Future.ap = createUnaryDispatcher(FL.ap);
Future.swap = createNullaryDispatcher('swap');
Future.fork = createBinaryDispatcher('fork');
Future.race = createUnaryDispatcher('race');
Future.or = createUnaryDispatcher('or');
Future.fold = createBinaryDispatcher('fold');
Future.hook = createInvertedBinaryDispatcher('hook');
Future.finally = createUnaryDispatcher('finally');
Future.value = createUnaryDispatcher('value');
Future.promise = createNullaryDispatcher('promise');
Future.cache = createNullaryDispatcher('cache');
FutureRace.prototype.toString = function FutureRace$toString(){
return `${this._left.toString()}.race(${this._right.toString()})`;
}
/////////////////////
// Other functions //
/////////////////////
//----------
Future.isFuture = isFuture;
Future.isForkable = isForkable;
function FutureAnd(left, right){
this._left = left;
this._right = right;
}
Future.reject = function Future$reject(x){
return new FutureClass(false, function Future$reject$fork(rej){
rej(x);
return noop;
});
};
FutureAnd.prototype = Object.create(Future.prototype);
Future.after = function Future$after(n, x){
if(arguments.length === 1) return unaryPartial(Future.after, n);
check$after(n);
return new FutureClass(false, function Future$after$fork(rej, res){
const t = setTimeout(res, n, x);
return function Future$after$cancel(){ clearTimeout(t) };
});
};
FutureAnd.prototype._f = function FutureAnd$fork(rej, res){
let rejected = false, resolved = false, val, lcancel = noop, rcancel = noop;
lcancel = this._left._f(
e => (rejected = true, rcancel(), rej(e)),
_ => rejected ? rej(val) : resolved ? res(val) : (resolved = true)
);
rcancel = this._right._f(
e => resolved ? rej(e) : (rejected = true, val = e),
x => resolved ? res(x) : (resolved = true, val = x)
);
return function FutureAnd$fork$cancel(){ lcancel(); rcancel() };
}
Future.cast = function Future$cast(m){
check$cast(m);
return new FutureClass(true, function Future$cast$fork(rej, res){
m.fork(rej, res);
});
};
FutureAnd.prototype.toString = function FutureAnd$toString(){
return `${this._left.toString()}.and(${this._right.toString()})`;
}
Future.encase = function Future$encase(f, x){
check$encase(f);
if(arguments.length === 1) return unaryPartial(Future.encase, f);
return new FutureClass(false, function Future$encase$fork(rej, res){
let r;
try{ r = f(x) }catch(e){ return void rej(e) }
res(r);
return noop;
});
};
//----------
Future.encase2 = function Future$encase2(f, x, y){
check$encase2(f);
if(arguments.length === 1) return unaryPartial(Future.encase2, f);
if(arguments.length === 2) return binaryPartial(Future.encase2, f, x);
return new FutureClass(false, function Future$encase2$fork(rej, res){
let r;
try{ r = f(x, y) }catch(e){ return void rej(e) }
res(r);
return noop;
function FutureOr(left, right){
this._left = left;
this._right = right;
}
FutureOr.prototype = Object.create(Future.prototype);
FutureOr.prototype._f = function FutureOr$fork(rej, res){
let resolved = false, rejected = false, val, err, lcancel = noop, rcancel = noop;
lcancel = this._left._f(
_ => rejected ? rej(err) : resolved ? res(val) : (rejected = true),
x => (resolved = true, rcancel(), res(x))
);
resolved || (rcancel = this._right._f(
e => resolved || (rejected ? rej(e) : (err = e, rejected = true)),
x => resolved || (rejected ? res(x) : (val = x, resolved = true))
));
return function FutureOr$fork$cancel(){ lcancel(); rcancel() };
}
FutureOr.prototype.toString = function FutureOr$toString(){
return `${this._left.toString()}.or(${this._right.toString()})`;
}
//----------
function FutureBoth(left, right){
this._left = left;
this._right = right;
}
FutureBoth.prototype = Object.create(Future.prototype);
FutureBoth.prototype._f = function FutureBoth$fork(rej, res){
let resolved = false, rejected = false, lcancel = noop, rcancel = noop;
const tuple = new Array(2);
lcancel = this._left._f(function FutureBoth$fork$rejLeft(e){
rejected = true; rcancel(); rej(e);
}, function FutureBoth$fork$resLeft(x){
tuple[0] = x;
if(resolved) res(tuple);
else (resolved = true);
});
};
rejected || (rcancel = this._right._f(function FutureBoth$fork$rejRight(e){
rejected = true; lcancel(); rej(e);
}, function FutureBoth$fork$resRight(x){
tuple[1] = x;
if(resolved) res(tuple);
else (resolved = true);
}));
return function FutureBoth$fork$cancel(){ lcancel(); rcancel() };
}
Future.encase3 = function Future$encase3(f, x, y, z){
check$encase3(f);
if(arguments.length === 1) return unaryPartial(Future.encase3, f);
if(arguments.length === 2) return binaryPartial(Future.encase3, f, x);
if(arguments.length === 3) return ternaryPartial(Future.encase3, f, x, y);
return new FutureClass(false, function Future$encase3$fork(rej, res){
let r;
try{ r = f(x, y, z) }catch(e){ return void rej(e) }
res(r);
return noop;
FutureBoth.prototype.toString = function FutureBoth$toString(){
return `${this._left.toString()}.both(${this._right.toString()})`;
}
//----------
function FutureFold(parent, lfold, rfold){
this._parent = parent;
this._lfold = lfold;
this._rfold = rfold;
}
FutureFold.prototype = Object.create(Future.prototype);
FutureFold.prototype._f = function FutureFold$fork(rej, res){
const _this = this;
return _this._parent._f(function FutureFold$fork$rej(x){
res(_this._lfold(x));
}, function FutureFold$fork$res(x){
res(_this._rfold(x));
});
};
}
Future.try = function Future$try(f){
return Future.encase(f, undefined);
};
FutureFold.prototype.toString = function FutureFold$toString(){
return `${this._parent.toString()}.fold(${showf(this._lfold)}, ${showf(this._rfold)})`;
}
Future.node = function Future$node(f){
check$node(f);
return new FutureClass(true, function Future$node$fork(rej, res){
f(function Future$node$done(a, b){
a ? rej(a) : res(b);
});
//----------
function check$hook$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the first function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function check$hook$g(m, g, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the second function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(g)}\n With: ${show(x)}`
);
}
function FutureHook(acquire, dispose, consume){
this._acquire = acquire;
this._dispose = dispose;
this._consume = consume;
}
FutureHook.prototype = Object.create(Future.prototype);
FutureHook.prototype._f = function FutureHook$fork(rej, res){
const _this = this;
let cancel, cancelAcquire = noop;
cancelAcquire = _this._acquire._f(rej, function FutureHook$fork$res(resource){
const disposer = function FutureHook$dispose(callback){
const disposal = _this._dispose(resource);
check$hook$f(disposal, _this._dispose, resource);
cancel = disposal._f(rej, callback);
return cancel;
}
const consumption = _this._consume(resource);
check$hook$g(consumption, _this._consume, resource);
cancel = function FutureHook$fork$cancelConsume(){
disposer(noop)();
cancelAcquire();
cancelConsume();
}
const cancelConsume = consumption._f(
x => disposer(_ => rej(x)),
x => disposer(_ => res(x))
);
});
};
cancel = cancel || cancelAcquire;
return function FutureHook$fork$cancel(){ cancel() };
}
Future.parallel = function Future$parallel(i, ms){
if(arguments.length === 1) return unaryPartial(Future.parallel, i);
check$parallel(i, ms);
const l = ms.length;
return l < 1 ? Future$of([]) : new FutureClass(false, function Future$parallel$fork(rej, res){
let ko = false;
let ok = 0;
const cs = [];
const out = new Array(l);
const next = j => i < l ? fork(ms[i], i++) : (j === l && res(out));
const fork = (m, j) => (check$parallel$m(m, j), cs[j] = m._f(
e => ko || (rej(e), ko = true),
x => ko || (out[j] = x, next(++ok))
));
ms.slice(0, i).forEach(fork);
return function Future$parallel$cancel(){ cs.forEach(call) };
FutureHook.prototype.toString = function FutureHook$toString(){
return `${this._acquire.toString()}.hook(${showf(this._dispose)}, ${showf(this._consume)})`;
}
//----------
function FutureFinally(left, right){
this._left = left;
this._right = right;
}
FutureFinally.prototype = Object.create(Future.prototype);
FutureFinally.prototype._f = function FutureFinally$fork(rej, res){
const _this = this;
let cancel;
const r = _this._left._f(function FutureFinally$fork$rej(e){
cancel = _this._right._f(rej, function FutureFinally$fork$rej$res(){ rej(e) });
}, function FutureFinally$fork$res(x){
cancel = _this._right._f(rej, function FutureFinally$fork$res$res(){ res(x) });
});
};
return cancel || (cancel = r, function FutureFinally$fork$cancel(){ cancel() });
}
Future.do = function Future$do(f){
check$do(f);
return new FutureClass(false, function Future$do$fork(rej, res){
const g = f();
check$do$g(g);
return Future$chainRec(function Future$do$next(next, _, x){
const o = g.next(x);
check$do$next(o);
return o.done ? Future$of(o) : o.value.map(next);
}, undefined)._f(rej, res);
});
FutureFinally.prototype.toString = function FutureFinally$toString(){
return `${this._left.toString()}.finally(${this._right.toString()})`;
}
Future.subclasses = {
SafeFuture,
ChainRec,
CachedFuture,
FutureOf,
FutureReject,
FutureNode,
FutureAfter,
FutureParallel,
FutureDo,
FutureCast,
FutureTry,
FutureEncase,
FutureChain,
FutureChainRej,
FutureMap,
FutureMapRej,
FutureBimap,
FutureAp,
FutureSwap,
FutureRace,
FutureAnd,
FutureOr,
FutureBoth,
FutureFold,
FutureHook,
FutureFinally
};

@@ -927,0 +1442,0 @@

{
"name": "fluture",
"version": "3.1.1",
"version": "4.0.0",
"description": "FantasyLand compliant (monadic) alternative to Promises",

@@ -12,10 +12,12 @@ "main": "fluture.js",

"post-merge": "npm install && npm dedupe && npm run check-security && npm outdated --long",
"pre-push": "npm test",
"pre-push": "npm run lint && npm run test:unit",
"release": "xyz --edit --tag 'X.Y.Z' --increment",
"setup": "npm run post-merge && cp scripts/hooks/* .git/hooks && git config push.followTags true",
"toc": "node scripts/toc.js",
"test": "npm run clean && npm run lint && npm run test:unit && npm run test:coverage",
"test": "npm run test:all && codecov",
"test:opt": "node --allow-natives-syntax --trace-opt --trace-deopt --trace-inlining scripts/test-opt",
"test:mem": "node scripts/test-mem",
"test:all": "npm run lint && npm run test:unit && npm run test:coverage",
"test:unit": "node ./node_modules/.bin/_mocha --ui bdd --reporter spec --check-leaks --full-trace",
"test:coverage": "node node_modules/.bin/istanbul cover --report html ./node_modules/.bin/_mocha -- --ui bdd --reporter dot --bail --check-leaks && codecov"
"test:coverage": "npm run clean && node node_modules/.bin/istanbul cover --report html ./node_modules/.bin/_mocha -- --ui bdd --reporter dot --bail"
},

@@ -54,3 +56,4 @@ "author": "Aldwin Vlasblom <aldwin.vlasblom@gmail.com> (https://github.com/Avaq)",

"dependencies": {
"inspect-f": "^1.1.0"
"inspect-f": "^1.1.0",
"sanctuary-type-classes": "^0.3.0"
},

@@ -63,3 +66,3 @@ "devDependencies": {

"eslint": "^3.0.1",
"fantasy-land": "^1.0.1",
"fantasy-land": "^2.0.0",
"fun-task": "^1.5.1",

@@ -69,3 +72,4 @@ "istanbul": "^0.4.2",

"lazy-either": "^1.0.3",
"markdown-toc": "^0.12.6",
"lodash.curry": "^4.1.1",
"markdown-toc": "^0.13.0",
"mocha": "^3.0.2",

@@ -77,4 +81,5 @@ "nsp": "^2.2.0",

"rimraf": "^2.4.3",
"sanctuary": "^0.11.1"
"sanctuary": "^0.11.1",
"xyz": "^1.1.0"
}
}

@@ -70,3 +70,2 @@ # Fluture

* [chain](#chain)
* [recur](#recur)
* [ap](#ap)

@@ -87,3 +86,5 @@ * [swap](#swap)

* [race](#race)
* [and](#and)
* [or](#or)
* [both](#both)
* [parallel](#parallel)

@@ -95,2 +96,3 @@ 1. [Utility functions](#utility-functions)

* [do](#do)
1. [Sanctuary](#sanctuary)
1. [Futurization](#futurization)

@@ -122,6 +124,10 @@ - [Benchmarks](#benchmarks)

- **Future** - Instances of Future provided by Fluture.
- **Functor** - Values which conform to the [Fantasy Land Functor specification][12].
- **Bifunctor** - Values which conform to the [Fantasy Land Bifunctor specification][24].
- **Chain** - Values which conform to the [Fantasy Land Chain specification][13].
- **Apply** - Values which conform to the [Fantasy Land Apply specification][14].
- **Functor** - Values which conform to the [Fantasy Land Functor specification][12]
as determined by [Sanctuary Type Classes][27].
- **Bifunctor** - Values which conform to the [Fantasy Land Bifunctor specification][24]
as determined by [Sanctuary Type Classes][28].
- **Chain** - Values which conform to the [Fantasy Land Chain specification][13]
as determined by [Sanctuary Type Classes][29].
- **Apply** - Values which conform to the [Fantasy Land Apply specification][14]
as determined by [Sanctuary Type Classes][30].
- **Iterator** - Objects with `next`-methods which conform to the [Iterator protocol][18].

@@ -158,8 +164,6 @@ - **Iteration** - `{done, value}`-Objects as defined by the [Iterator protocol][18].

#### of
##### `#of :: a -> Future _ a`
##### `.of :: a -> Future _ a`
Creates a Future which immediately resolves with the given value. This function
is compliant with the [Fantasy Land Applicative specification][16] and is
also available on the prototype.
is compliant with the [Fantasy Land Applicative specification][16].

@@ -192,2 +196,13 @@ ```js

#### rejectAfter
##### `.rejectAfter :: Number -> a -> Future a b`
Creates a Future which rejects with the given reason after n milliseconds.
```js
const eventualError = Future.rejectAfter(500, new Error('Kaputt!'));
eventualError.fork(err => console.log('Oh no - ' + err.message), console.log);
//! Oh no - Kaputt!
```
#### cast

@@ -340,16 +355,7 @@ ##### `.cast :: Forkable a b -> Future a b`

#### recur
##### `#recur :: Future a b ~> (b -> Future a c) -> Future a c`
##### `.recur :: (b -> Future a c) -> Future a b -> Future a c`
Note that, due to its lazy nature, the stack and/or heap will slowly fill up as
you chain more over the same structure. It's therefore recommended that you use
[`chainRec`](#chainrec) in cases where you wish to `chain` recursively or
traverse a large list (10000+ items).
An alternative version of `chain` which does not build up the cancel function.
This is useful in the case of a never-resolving recursive computation, in
order to prevent stack-overflow or out-of-memory errors:
```js
const recursive = () => Future.after(200, 'world').recur(recursive);
const cancel = recursive();
process.on('SIGINT', cancel);
```
#### ap

@@ -359,6 +365,6 @@ ##### `#ap :: Future a b ~> Future a (b -> c) -> Future a c`

Applies the function contained in the right-hand Future to the value contained
in the left-hand Future. Both Futures involved will run in parallel, and if one
rejects the resulting Future will also be rejected. To learn more about the
exact behaviour of `ap`, check out its [spec][14].
Applies the function contained in the right-hand Future or Apply to the value
contained in the left-hand Future or Apply. If one of the Futures rejects the
resulting Future will also be rejected. To learn more about the exact behaviour
of `ap`, check out its [spec][14].

@@ -476,10 +482,27 @@ ```js

Be careful when cancelling a hooked Future. If the resource was acquired but not
yet consumed, it will no longer be disposed. One way to work around this is to
have the `consume` computation return a cancel function which forcefully
disposes of the resource.
In the case that a hooked Future is *cancelled* after the resource was acquired,
`dispose` will be executed and immediately cancelled. This means that rejections
which may happen during this disposal are **silently ignored**. To ensure that
resources are disposed during cancellation, you might synchronously dispose
resources in the `cancel` function of the disposal Future:
Take care when using this in combination with [`cache`](#cache). Hooking relies
on the first operation providing a fresh resource every time it's forked.
```js
const closeConnection = conn => Future((rej, res) => {
//We try to dispose gracefully.
conn.flushGracefully(err => {
if(err === null){
conn.close();
res();
}else{
rej(err);
}
});
//On cancel, we force dispose.
return () => conn.close();
});
```
#### finally

@@ -521,3 +544,3 @@ ##### `#finally :: Future a b ~> Future a c -> Future a b`

Execute the computation that was passed to the Future at [construction](#Future)
Execute the computation that was passed to the Future at [construction](#future)
using the given `reject` and `resolve` callbacks.

@@ -615,2 +638,22 @@

#### and
##### `#and :: Future a b ~> Future a b -> Future a b`
##### `.and :: Future a b -> Future a b -> Future a b`
Logical and for Futures.
Returns a new Future which either rejects with the first rejection reason, or
resolves with the last resolution value once and if both Futures resolve.
This behaves analogues to how JavaScript's and operator does, except both
Futures run simultaneously, so it is *not* short-circuited. That means that
if the second has side-effects, they will run (and possibly be cancelled) even
if the first rejects.
```js
//An asynchronous version of:
//const result = isResolved() && getValue();
const result = isResolved().and(getValue());
```
#### or

@@ -648,2 +691,17 @@ ##### `#or :: Future a b ~> Future a b -> Future a b`

#### both
##### `#both :: Future a b ~> Future a b -> Future a b`
##### `.both :: Future a b -> Future a b -> Future a b`
Run two Futures in parallel. Basically like calling
[`Future.parallel`](#parallel) with exactly two Futures:
```js
Future.parallel(2, [a, b])
===
Future.both(a, b)
===
a.both(b)
```
#### parallel

@@ -789,2 +847,39 @@ ##### `.parallel :: PositiveInteger -> Array (Future a b) -> Future a (Array b)`

### Sanctuary
When using this module with [Sanctuary][21], you might run into the following:
```js
const S = require('sanctuary');
const Future = require('fluture');
S.I(Future.of(1));
//! Since there is no type of which all the above values are members,
//! the type-variable constraint has been violated.
```
This happens because Sanctuary needs to know about the Future type in order to
determine whether the type-variable used in the definition of `S.I` is
consistent.
To let Sanctuary know about Futures, we can provide it a `FutureType` using
[Sanctuary Def][31], and pass it to Sanctuary using [`S.create`][32]
```js
const $ = require('sanctuary-def');
const Future = require('fluture');
const {env, create} = require('sanctuary');
const FutureType = $.BinaryType(
Future.name,
Future.isFuture,
Future.extractLeft,
Future.extractRight
);
const S = create({checkTypes: true, env: env.concat([FutureType])});
S.I(Future.of(1));
//> Future.of(1)
```
### Futurization

@@ -851,1 +946,7 @@

[26]: https://github.com/fantasyland/fantasy-land#chainrec
[27]: https://github.com/sanctuary-js/sanctuary-type-classes#Functor
[28]: https://github.com/sanctuary-js/sanctuary-type-classes#Bifunctor
[29]: https://github.com/sanctuary-js/sanctuary-type-classes#Chain
[30]: https://github.com/sanctuary-js/sanctuary-type-classes#Apply
[31]: https://github.com/sanctuary-js/sanctuary-def#binarytype
[32]: https://sanctuary.js.org/#create
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc