Functional application: Allow any granularity of arguments (currying, essentially).

This commit is contained in:
David Braun 2017-10-17 10:34:17 -04:00
parent 04bbe30a00
commit d7c117619a
3 changed files with 17 additions and 31 deletions

View file

@ -295,9 +295,9 @@ channel.slice(10);
Channel.slice(10, Infinity, channel); Channel.slice(10, Infinity, channel);
``` ```
You can also use partial application to pass the channel in later: You can also use partial application:
```JavaScript ```JavaScript
const skipTen = Channel.slice(10, Infinity); Channel.slice(10, Infinity)(channel);
skipTen(channel); Channel.slice(10)(Infinity)(channel);
``` ```

View file

@ -339,23 +339,22 @@ Channel.select = methodPromises =>
// functional interface allowing full or partial application // functional interface allowing full or partial application
// //
// Channel.slice(10, Infinity, channel) // Channel.slice(10, Infinity, channel)
// // Channel.slice(10, Infinity)(channel)
// or // Channel.slice(10)(Infinity)(channel)
//
// const skipTen = Channel.slice(10, Infinity)
// skipTen(channel)
const channel = Channel(); const channel = Channel();
const methods = Object.keys(channel).concat(Object.keys(channel.readOnly())); const methods = Object.keys(channel).concat(Object.keys(channel.readOnly()));
methods.forEach(method => { methods.forEach(method => {
Channel[method] = (...args) => { const bound = function(...args) {
const arity = method === `slice` ? 3 : channel[method].length; const arity = method === `slice` ? 3 : channel[method].length;
return args.length >= arity return args.length >= arity
? args[arity - 1][method](...args.slice(0, arity - 1)) ? args[arity - 1][method](...args.slice(0, arity - 1))
: channel => channel[method](...args); : bound.bind(this, ...args);
}; };
Channel[method] = bound;
}); });
module.exports = Object.freeze(Channel); module.exports = Object.freeze(Channel);

View file

@ -129,26 +129,6 @@ describe(`Channel`, function() {
}); });
describe(`functional interface`, async function() { describe(`functional interface`, async function() {
describe(`map`, function() {
it(`full application`, async function() {
assert.deepEqual(
await toArray(
Channel.map(value => value.toUpperCase(), Channel.of(`a`, `b`, `c`))
),
[`A`, `B`, `C`]
);
});
it(`partial application`, async function() {
assert.deepEqual(
await toArray(
Channel.map(value => value.toUpperCase())(Channel.of(`a`, `b`, `c`))
),
[`A`, `B`, `C`]
);
});
});
describe(`slice`, function() { describe(`slice`, function() {
it(`full application`, async function() { it(`full application`, async function() {
assert.deepEqual( assert.deepEqual(
@ -157,7 +137,14 @@ describe(`functional interface`, async function() {
); );
}); });
it(`partial application`, async function() { it(`single argument application`, async function() {
assert.deepEqual(
await toArray(Channel.slice(1)(4)(Channel.of(0, 1, 2, 3, 4))),
[1, 2, 3]
);
});
it(`double argument application`, async function() {
assert.deepEqual( assert.deepEqual(
await toArray(Channel.slice(1, 4)(Channel.of(0, 1, 2, 3, 4))), await toArray(Channel.slice(1, 4)(Channel.of(0, 1, 2, 3, 4))),
[1, 2, 3] [1, 2, 3]