Skip to content

Commit 812e085

Browse files
committed
feat: support for middlewares for recursive
1 parent 3b62612 commit 812e085

File tree

4 files changed

+97
-12
lines changed

4 files changed

+97
-12
lines changed

README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,41 @@
66

77
Create recursive functions with `Y-Combinator` style.
88
```js
9+
import { recursive } from 'recursive-func'
10+
11+
const log = next => (...args) => {
12+
const result = next(...args)
13+
14+
// will print from the last call to the first
15+
console.log('Args = ', args)
16+
console.log('Result = ', result)
17+
18+
return result
19+
}
20+
21+
const middlewares = [log]
22+
923
const sum = recursive(self => ([head = 0, ...tail]) => {
1024
return tail.length === 0
1125
? head
1226
: head + self(tail)
13-
})
27+
}, middlewares)
28+
29+
const value = sum([1, 2, 3])
30+
31+
// third call:
32+
// Args = [[3]]
33+
// Result = 3
34+
35+
// second call:
36+
// Args = [[2, 3]]
37+
// Result = 5
38+
39+
// first call:
40+
// Args = [[1, 2, 3]]
41+
// Result = 6
1442

15-
sum([1, 2, 3]) // => 6
43+
console.log(value) // => 6
1644
```
1745

1846
[build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square

src/compose.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const base = (f, g) => (...args) => f(g(...args))
2+
3+
const compose = (funcs) => funcs.reduce(base)
4+
5+
export default compose

src/recursive.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1-
const recursive = (func) => {
2-
const wrapper = func((...args) => wrapper(...args))
1+
import compose from './compose'
2+
3+
const applyMiddlewares = (middlewares, func) => (
4+
middlewares.length !== 0
5+
? compose(middlewares)(func)
6+
: func
7+
)
8+
9+
const recursive = (func, middlewares = []) => {
10+
const wrapper = applyMiddlewares(
11+
middlewares,
12+
func((...args) => wrapper(...args))
13+
)
14+
315
return wrapper
416
}
517

tests/index-test.js

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,78 @@ import expect, { createSpy } from 'expect'
33
import { recursive } from 'src/index'
44

55
describe('recursive', () => {
6+
let id
7+
let constant
8+
9+
beforeEach(() => {
10+
id = createSpy().andCall(value => value)
11+
constant = createSpy().andCall(value => _ => value)
12+
})
13+
614
it('should be a function', () => {
715
expect(recursive).toBeA(Function)
816
})
917

10-
describe('recursive(identity)("one", "two")', () => {
11-
let internal
12-
let identity
18+
describe('recursive(id)("one", "two")', () => {
19+
let rec
1320

1421
beforeEach(() => {
15-
internal = createSpy().andCall(value => value)
16-
identity = recursive(self => internal)
22+
rec = recursive(self => id)
1723
})
1824

19-
const subject = () => identity('one', 'two')
25+
const subject = () => rec('one', 'two')
2026

2127
it('should be called with ("one", "two")', () => {
2228
subject()
2329

24-
expect(internal).toHaveBeenCalledWith('one', 'two')
30+
expect(id).toHaveBeenCalledWith('one', 'two')
2531
})
2632

2733
it('should be called 1 time', () => {
2834
subject()
2935

30-
expect(internal.calls.length).toEqual(1)
36+
expect(id.calls.length).toEqual(1)
3137
})
3238

3339
it('should return "one"', () => {
3440
expect(subject()).toEqual('one')
3541
})
3642
})
3743

44+
describe('recursive(id, [() => const("three")])("one", "two")', () => {
45+
let subject
46+
let middleware
47+
48+
beforeEach(() => {
49+
middleware = createSpy().andCall(() => constant('three'))
50+
subject = recursive(self => id, [
51+
middleware,
52+
])
53+
})
54+
55+
it('should not call λ(id)', () => {
56+
subject()
57+
58+
expect(id).toNotHaveBeenCalled()
59+
})
60+
61+
it('should call λ(middleware) with λ(id)', () => {
62+
subject()
63+
64+
expect(middleware).toHaveBeenCalled(id)
65+
})
66+
67+
it('should call λ(const) with λ(three)', () => {
68+
subject()
69+
70+
expect(constant).toHaveBeenCalled('three')
71+
})
72+
73+
it('should return "three"', () => {
74+
expect(subject('one', 'two')).toEqual('three')
75+
})
76+
})
77+
3878
describe('recursive(sum)([1, 2, 3])', () => {
3979
let internal
4080
let sum

0 commit comments

Comments
 (0)