+87
-14
@@ -52,9 +52,9 @@ /*global define FantasyLand inspectf*/ | ||
| : Array.isArray(x) | ||
| ? `[Array ${x.length}]` | ||
| ? `[Array: ${x.length}]` | ||
| : typeof x === 'function' | ||
| ? typeof x.name === 'string' && x.name.length > 0 | ||
| ? `[Function ${x.name}]` | ||
| ? `[Function: ${x.name}]` | ||
| : '[Function]' | ||
| : x && x.toString === Object.prototype.toString | ||
| ? `[Object ${Object.keys(x).map(String).join(', ')}]` | ||
| ? `[Object: ${Object.keys(x).map(String).join(', ')}]` | ||
| : String(x); | ||
@@ -74,9 +74,15 @@ | ||
| const padf = (sf, s) => s.replace(/^/gm, sf).trim(); | ||
| const padf = (sf, s) => s.replace(/^/gm, sf).replace(sf, ''); | ||
| const showf = f => padf(' ', inspectf(2, f)); | ||
| const fid = f => f.name ? f.name : /*istanbul ignore next*/ '<anonymous>'; | ||
| const fid = f => f.name ? f.name : '<anonymous>'; | ||
| //Partially apply a function with a single argument. | ||
| function unaryPartial(f, a){ | ||
| const g = function partial(b, c){ return arguments.length > 1 ? f(a, b, c) : f(a, b) }; | ||
| const g = function partial(b, c, d){ | ||
| switch(arguments.length){ | ||
| case 1: return f(a, b); | ||
| case 2: return f(a, b, c); | ||
| default: return f(a, b, c, d); | ||
| } | ||
| }; | ||
| g.toString = () => `${inspectf(2, f)}.bind(null, ${show(a)})`; | ||
@@ -89,3 +95,3 @@ g.inspect = () => `[Function: unaryPartial$${fid(f)}]`; | ||
| function binaryPartial(f, a, b){ | ||
| const g = function partial(c){ return f(a, b, c) }; | ||
| const g = function partial(c, d){ return arguments.length === 1 ? f(a, b, c) : f(a, b, c, d) }; | ||
| g.toString = () => `${inspectf(2, f)}.bind(null, ${show(a)}, ${show(b)})`; | ||
@@ -96,2 +102,10 @@ g.inspect = () => `[Function: binaryPartial$${fid(f)}]`; | ||
| //Partially apply a function with three arguments. | ||
| function ternaryPartial(f, a, b, c){ | ||
| const g = function partial(d){ return f(a, b, c, d) }; | ||
| g.toString = () => `${inspectf(2, f)}.bind(null, ${show(a)}, ${show(b)}, ${show(c)})`; | ||
| g.inspect = () => `[Function: ternaryPartial$${fid(f)}]`; | ||
| return g; | ||
| } | ||
| //////////// | ||
@@ -216,2 +230,10 @@ // Errors // | ||
| function check$encase2(f){ | ||
| if(typeof f !== 'function') error$invalidArgument('Future.encase2', 0, 'be a function', f); | ||
| } | ||
| function check$encase3(f){ | ||
| if(typeof f !== 'function') error$invalidArgument('Future.encase3', 0, 'be a function', f); | ||
| } | ||
| function check$node(f){ | ||
@@ -428,2 +450,18 @@ if(typeof f !== 'function') error$invalidArgument('Future.node', 0, 'be a function', f); | ||
| //Expose utilities, mainly for unit testing. | ||
| Future.util = { | ||
| isForkable, | ||
| isFuture, | ||
| isFunction, | ||
| isPositiveInteger, | ||
| preview, | ||
| show, | ||
| padf, | ||
| showf, | ||
| fid, | ||
| unaryPartial, | ||
| binaryPartial, | ||
| ternaryPartial | ||
| }; | ||
| ///////////////// | ||
@@ -548,18 +586,53 @@ // Dispatchers // | ||
| //encase :: (a -> !b | c) -> a -> Future b c | ||
| //encase :: (a -> !e | r) -> a -> Future e r | ||
| Future.encase = function Future$encase(f, x){ | ||
| check$encase(f); | ||
| if(arguments.length === 1) return unaryPartial(Future.encase, f); | ||
| check$encase(f); | ||
| return new FutureClass(function Future$encase$fork(rej, res){ | ||
| let y; | ||
| let r; | ||
| try{ | ||
| y = f(x); | ||
| r = f(x); | ||
| } | ||
| catch(err){ | ||
| return void rej(err); | ||
| catch(e){ | ||
| return void rej(e); | ||
| } | ||
| res(y); | ||
| res(r); | ||
| }); | ||
| }; | ||
| //encase2 :: (a, b -> !e | r) -> a -> b -> Future e r | ||
| 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(function Future$encase2$fork(rej, res){ | ||
| let r; | ||
| try{ | ||
| r = f(x, y); | ||
| } | ||
| catch(e){ | ||
| return void rej(e); | ||
| } | ||
| res(r); | ||
| }); | ||
| }; | ||
| //encase3 :: (a, b, c -> !e | r) -> a -> b -> c -> Future e r | ||
| 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(function Future$encase3$fork(rej, res){ | ||
| let r; | ||
| try{ | ||
| r = f(x, y, z); | ||
| } | ||
| catch(e){ | ||
| return void rej(e); | ||
| } | ||
| res(r); | ||
| }); | ||
| }; | ||
| //Create a Future which resolves with the return value of the given function, | ||
@@ -566,0 +639,0 @@ //or rejects with the exception thrown by the given function. |
+1
-1
| { | ||
| "name": "fluture", | ||
| "version": "0.6.3", | ||
| "version": "0.6.4", | ||
| "description": "A mathematically correct alternative to Promises for asynchronous control flow", | ||
@@ -5,0 +5,0 @@ "main": "fluture.js", |
+19
-11
@@ -156,4 +156,18 @@ # Fluture | ||
| #### `encase :: (a -> !b | c) -> a -> Future b c` | ||
| #### `try :: (Void -> !a | b) -> Future a b` | ||
| Creates a Future which resolves with the result of calling the given function, | ||
| or rejects with the error thrown by the given function. | ||
| Sugar for `Future.encase(f, undefined)`. | ||
| ```js | ||
| const data = {foo: 'bar'} | ||
| Future.try(() => data.foo.bar.baz) | ||
| .fork(console.error, console.log) | ||
| //> [TypeError: Cannot read property 'baz' of undefined] | ||
| ``` | ||
| #### `encase :: (a -> !e | r) -> a -> Future e r` | ||
| Creates a Future which resolves with the result of calling the given function | ||
@@ -169,15 +183,9 @@ with the given value, or rejects with the error thrown by the function. | ||
| #### `try :: (Void -> !a | b) -> Future a b` | ||
| #### `encase2 :: (a, b -> !e | r) -> a -> b -> Future e r` | ||
| Creates a Future which resolves with the result of calling the given function, | ||
| or rejects with the error thrown by the given function. | ||
| Binary version of `Future.encase`. | ||
| Sugar for `Future.encase(f, undefined)`. | ||
| #### `encase3 :: (a, b, c -> !e | r) -> a -> b -> c -> Future e r` | ||
| ```js | ||
| const data = {foo: 'bar'} | ||
| Future.try(() => data.foo.bar.baz) | ||
| .fork(console.error, console.log) | ||
| //> [TypeError: Cannot read property 'baz' of undefined] | ||
| ``` | ||
| Ternary version of `Future.encase`. | ||
@@ -184,0 +192,0 @@ #### `node :: ((a, b -> Void) -> Void) -> Future a b` |
41120
5.68%572
13.27%575
1.41%