|
| 1 | +// ES6 Curry & Function Composition |
| 2 | + |
1 | 3 | import test from 'tape';
|
| 4 | +import { add2 } from './index'; |
| 5 | +import { add3 } from './index'; |
| 6 | +import { inc } from './index'; |
| 7 | +import { compose2 } from './index'; |
| 8 | +import { trace } from './index'; |
| 9 | +import { compose } from './index'; |
| 10 | + |
| 11 | +// What is currying? |
| 12 | +// add2(a) => b => Number |
| 13 | +test('add2(a) => b => Number', assert => { |
| 14 | + const msg = 'should take two numbers and return the sum'; |
| 15 | + |
| 16 | + const actual = add2(1)(2); |
| 17 | + const expected = 3; |
| 18 | + |
| 19 | + assert.same(actual, expected, msg); |
| 20 | + assert.end(); |
| 21 | +}); |
| 22 | + |
| 23 | +// What is partial application? |
| 24 | +// add3(a) => b => c => Number |
| 25 | +test('add3(a) => b => c => Number', assert => { |
| 26 | + const msg = 'should auto-curry arguments and return the sum'; |
| 27 | + |
| 28 | + const expected = 6; |
| 29 | + |
| 30 | + assert.same(add3(1, 2, 3), expected, msg); |
| 31 | + assert.same(add3(1)(2)(3), expected, msg); |
| 32 | + assert.same(add3(1)(2, 3), expected, msg); |
| 33 | + assert.same(add3(1, 2)(3), expected, msg); |
| 34 | + assert.end(); |
| 35 | +}); |
| 36 | + |
| 37 | +// What is point-free style? |
| 38 | +// inc(n) => Number |
| 39 | +test('inc(n) => Number', assert => { |
| 40 | + const msg = 'should take a number a and return the sum of a and 1'; |
| 41 | + |
| 42 | + const actual = inc(4); |
| 43 | + const expected = 5; |
| 44 | + |
| 45 | + assert.same(actual, expected, msg); |
| 46 | + assert.end(); |
| 47 | +}); |
| 48 | + |
| 49 | +// What is function composition? |
| 50 | +// compose2(f: Function, g: Function) => Function |
| 51 | +// Given functions f and g, return the composition f ∘ g (f after g). |
| 52 | +// (f ∘ g)(x) = f(g(x)) |
| 53 | +test('compose2(f: Function, g: Function) => Function', assert => { |
| 54 | + const msg = 'should take two functions, f & g, and return f ∘ g'; |
| 55 | + |
| 56 | + const g = n => n + 1; |
| 57 | + const f = n => n * 2; |
| 58 | + const h = compose2(f, g); |
| 59 | + |
| 60 | + const actual = h(20); |
| 61 | + const expected = 42; |
| 62 | + |
| 63 | + assert.same(actual, expected, msg); |
| 64 | + assert.end(); |
| 65 | +}); |
| 66 | + |
| 67 | +// trace |
| 68 | +test('trace(label) => v => v, effects(log to console)', assert => { |
| 69 | + const msg = 'should take a label and value and log, "label: value"'; |
| 70 | + |
| 71 | + const actual = trace('foo')('bar'); |
| 72 | + const expected = 'bar'; |
| 73 | + |
| 74 | + assert.same(actual, expected, msg); |
| 75 | + assert.end(); |
| 76 | +}); |
| 77 | + |
| 78 | +// How does currying help with function composition? |
| 79 | +// compose(...fns: [...Functions]) => Function |
| 80 | +test('compose(...fns: [...Functions]) => Function', assert => { |
| 81 | + const msg = 'should take any number of functions and return their composition'; |
| 82 | + |
| 83 | + const g = n => n + 1; |
| 84 | + const f = n => n * 2; |
2 | 85 |
|
3 |
| -test('No tests yet!', assert => { |
4 |
| - const msg = 'should have tests'; |
| 86 | + const h = compose( |
| 87 | + trace('after f'), |
| 88 | + f, |
| 89 | + trace('after g'), |
| 90 | + g |
| 91 | + ); |
5 | 92 |
|
6 |
| - const actual = false; |
7 |
| - const expected = true; |
| 93 | + const actual = h(20); |
| 94 | + const expected = 42; |
8 | 95 |
|
9 | 96 | assert.same(actual, expected, msg);
|
10 | 97 | assert.end();
|
|
0 commit comments