Add functional API.

This commit is contained in:
David Braun 2017-10-11 03:32:47 -04:00
parent be51e95eb3
commit 8da51305eb
No known key found for this signature in database
GPG key ID: 5694EEC4D129BDCF
3 changed files with 91 additions and 2 deletions

View file

@ -228,6 +228,28 @@ Closed channels always return `undefined` immediately.
#### slice(start, end) -> Channel #### slice(start, end) -> Channel
### Functional API
There is a parallel API to support functional-style programming. Every channel
method is also available as an independent function in the `Channel` namespace
that takes a channel as the final argument. For example, `slice` can be called
in either of the following two ways:
```JavaScript
// method
channel.slice(10)
// function
Channel.slice(10, Infinity, channel)
```
You can also use partial application to pass the channel in later:
```JavaScript
const skipTen = Channel.slice(10, Infinity)
skipTen(channel)
```
# Contributing # Contributing
Please [submit an issue](https://github.com/NodeGuy/channel/issues/new) if you Please [submit an issue](https://github.com/NodeGuy/channel/issues/new) if you

View file

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

View file

@ -99,6 +99,45 @@ describe(`Channel`, function () {
break break
} }
}) })
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 () {
it(`full application`, async function () {
assert.deepEqual(
await toArray(Channel.slice(1, 4, Channel.of(0, 1, 2, 3, 4))),
[1, 2, 3]
)
})
it(`partial application`, async function () {
assert.deepEqual(
await toArray(Channel.slice(1, 4)(Channel.of(0, 1, 2, 3, 4))),
[1, 2, 3]
)
})
})
})
}) })
describe(`Channel object`, function () { describe(`Channel object`, function () {
@ -143,7 +182,9 @@ describe(`Channel object`, function () {
it(`filter`, async function () { it(`filter`, async function () {
assert.deepEqual( assert.deepEqual(
await toArray(Channel.of(0, 1, 2, 3, 4, 5).filter(x => x % 2 !== 0)), await toArray(Channel.of(0, 1, 2, 3, 4, 5)
.filter((value) => value % 2 !== 0)
),
[1, 3, 5] [1, 3, 5]
) )
}) })
@ -165,7 +206,9 @@ describe(`Channel object`, function () {
it(`map`, async function () { it(`map`, async function () {
assert.deepEqual( assert.deepEqual(
await toArray(Channel.of(`a`, `b`, `c`).map(x => x.toUpperCase())), await toArray(Channel.of(`a`, `b`, `c`)
.map((value) => value.toUpperCase())
),
[`A`, `B`, `C`] [`A`, `B`, `C`]
) )
}) })