1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 565 1 487 2071 144 247 1927 112 157 25 20 58 56 74 37 161 22 21 25 38 3 3 111 7 18 10 20 4 4 2 2 1 1 1 1 6 1 1 1 1 1 1 1 1 1 1 1 1 1117 | /* vim: set et sw=2 ts=2: */ 'use strict'; function id(x) { return x; } // **Partial application** // // While partial application of functions can be implemented easily // using JavaScript's `bind` or `apply` functions, it is more // efficient to use closures as JavaScript's native functions // additionally do some heavy error checking and deal with `this`. // // Partial application of functions relies on the `length` reported // by a function. A correct partial application returns a function // with a length // `length of function which is applied MINUS number of arguments consumed`. // Unfortunately this means we need to have some biolerplate code for // every arity of functions and results, thus the big blob of code // below. var funcs = { 0: id, 1: id, 2: function (__fn__) { return function (a, b) { switch (arguments.length) { case 1: return function (b) { return __fn__(a, b); }; } return __fn__(a, b); }; }, 3: function (__fn__) { return function (a, b, c) { switch (arguments.length) { case 1: return funcs[2](function (b, c) { return __fn__(a, b, c); }); case 2: return function (c) { return __fn__(a, b, c); }; } return __fn__(a, b, c); }; }, 4: function (__fn__) { return function (a, b, c, d) { switch (arguments.length) { case 1: return funcs[3](function (b, c, d) { return __fn__(a, b, c, d); }); case 2: return funcs[2](function (c, d) { return __fn__(a, b, c, d); }); case 3: return function (d) { return __fn__(a, b, c, d); }; } return __fn__(a, b, c, d); }; }, 5: function (__fn__) { return function (a, b, c, d, e) { switch (arguments.length) { case 1: return funcs[4](function (b, c, d, e) { return __fn__(a, b, c, d, e); }); case 2: return funcs[3](function (c, d, e) { return __fn__(a, b, c, d, e); }); case 3: return funcs[2](function (d, e) { return __fn__(a, b, c, d, e); }); case 4: return function (e) { return __fn__(a, b, c, d, e); }; } return __fn__(a, b, c, d, e); }; }, 6: function (__fn__) { return function (a, b, c, d, e, f) { switch (arguments.length) { case 1: return funcs[5](function (b, c, d, e, f) { return __fn__(a, b, c, d, e, f); }); case 2: return funcs[4](function (c, d, e, f) { return __fn__(a, b, c, d, e, f); }); case 3: return funcs[3](function (d, e, f) { return __fn__(a, b, c, d, e, f); }); case 4: return funcs[2](function (e, f) { return __fn__(a, b, c, d, e, f); }); case 5: return function (f) { return __fn__(a, b, c, d, e, f); }; } return __fn__(a, b, c, d, e, f); }; } }; // Turns an ordinary function into a function which can be partially applied. // The maximum arity that this can deal with is 8 (see above). module.exports = function curried(fn) { return funcs[fn.length](fn); }; |