Add functional API.
This commit is contained in:
parent
be51e95eb3
commit
8da51305eb
3 changed files with 91 additions and 2 deletions
22
README.md
22
README.md
|
@ -228,6 +228,28 @@ Closed channels always return `undefined` immediately.
|
|||
|
||||
#### 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
|
||||
|
||||
Please [submit an issue](https://github.com/NodeGuy/channel/issues/new) if you
|
||||
|
|
24
lib/index.js
24
lib/index.js
|
@ -311,4 +311,28 @@ Channel.select = (...methodPromises) => {
|
|||
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)
|
||||
|
|
|
@ -99,6 +99,45 @@ describe(`Channel`, function () {
|
|||
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 () {
|
||||
|
@ -143,7 +182,9 @@ describe(`Channel object`, function () {
|
|||
|
||||
it(`filter`, async function () {
|
||||
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]
|
||||
)
|
||||
})
|
||||
|
@ -165,7 +206,9 @@ describe(`Channel object`, function () {
|
|||
|
||||
it(`map`, async function () {
|
||||
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`]
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue