commit
9b1b6bb44a
@ -1,6 +1,7 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
|
* Add `u._` placeholder for curried functions.
|
||||||
|
|
||||||
## [0.6.0]
|
## [0.6.0]
|
||||||
* Remove support for `_.placeholder` in curried methods. This may come back, but it was necessary for the next item.
|
* Remove support for `_.placeholder` in curried methods. This may come back, but it was necessary for the next item.
|
||||||
|
13
README.md
13
README.md
@ -163,6 +163,19 @@ var result = u({ person: { [key]: 21 } }, { person: { name: 'Olivier P.', age: 2
|
|||||||
expect(result).toEqual({ person: { name: 'Olivier P.', age: 21 } });
|
expect(result).toEqual({ person: { name: 'Olivier P.', age: 21 } });
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `u._`
|
||||||
|
|
||||||
|
All updeep functions are curried.
|
||||||
|
If you want to partially apply a function in an order other than the default argument order, you can use the placeholder.
|
||||||
|
|
||||||
|
```js
|
||||||
|
function increment(i) { return i + 1; }
|
||||||
|
var updateJoe = u(u._, { name: "Joe Merrill", age: 21 });
|
||||||
|
var result = updateJoe({ age: increment });
|
||||||
|
|
||||||
|
expect(result).toEqual({ name: "Joe Merrill", age: 22 });
|
||||||
|
```
|
||||||
|
|
||||||
### `u.updateIn(path(, value)(, object))`
|
### `u.updateIn(path(, value)(, object))`
|
||||||
|
|
||||||
Update a single value with a simple string or array path.
|
Update a single value with a simple string or array path.
|
||||||
|
@ -8,9 +8,11 @@ import reject from './reject';
|
|||||||
import update from './update';
|
import update from './update';
|
||||||
import updateIn from './updateIn';
|
import updateIn from './updateIn';
|
||||||
import withDefault from './withDefault';
|
import withDefault from './withDefault';
|
||||||
|
import { _ } from './util/curry';
|
||||||
|
|
||||||
const u = update;
|
const u = update;
|
||||||
|
|
||||||
|
u._ = _;
|
||||||
u.if = _if;
|
u.if = _if;
|
||||||
u.ifElse = ifElse;
|
u.ifElse = ifElse;
|
||||||
u.is = is;
|
u.is = is;
|
||||||
|
@ -1,7 +1,20 @@
|
|||||||
/* eslint no-shadow:0 */
|
/* eslint no-shadow:0, no-param-reassign:0 */
|
||||||
|
export const _ = '@@updeep/placeholder';
|
||||||
|
|
||||||
|
function countArguments(args, max) {
|
||||||
|
let n = args.length;
|
||||||
|
if (n > max) n = max;
|
||||||
|
|
||||||
|
while (args[n - 1] === _) {
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
export function curry1(fn) {
|
export function curry1(fn) {
|
||||||
return function curried(a, b, c) {
|
return function curried(a, b, c) {
|
||||||
const n = arguments.length;
|
const n = countArguments(arguments);
|
||||||
|
|
||||||
if (n >= 1) return fn(a, b, c);
|
if (n >= 1) return fn(a, b, c);
|
||||||
return curried;
|
return curried;
|
||||||
@ -10,9 +23,17 @@ export function curry1(fn) {
|
|||||||
|
|
||||||
export function curry2(fn) {
|
export function curry2(fn) {
|
||||||
return function curried(a, b, c, d) {
|
return function curried(a, b, c, d) {
|
||||||
const n = arguments.length;
|
const n = countArguments(arguments, 2);
|
||||||
|
|
||||||
|
if (b === _ || c === _ || d === _) {
|
||||||
|
throw new Error('Can only use placeholder on first argument of this function.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n >= 2) {
|
||||||
|
if (a === _) return curry1((a, c, d) => fn(a, b, c, d));
|
||||||
|
return fn(a, b, c, d);
|
||||||
|
}
|
||||||
|
|
||||||
if (n >= 2) return fn(a, b, c, d);
|
|
||||||
if (n === 1) return curry1((b, c, d) => fn(a, b, c, d));
|
if (n === 1) return curry1((b, c, d) => fn(a, b, c, d));
|
||||||
return curried;
|
return curried;
|
||||||
};
|
};
|
||||||
@ -20,22 +41,71 @@ export function curry2(fn) {
|
|||||||
|
|
||||||
export function curry3(fn) {
|
export function curry3(fn) {
|
||||||
return function curried(a, b, c, d, e) {
|
return function curried(a, b, c, d, e) {
|
||||||
const n = arguments.length;
|
const n = countArguments(arguments, 3);
|
||||||
|
|
||||||
|
if (c === _ || d === _ || e === _) {
|
||||||
|
throw new Error('Can only use placeholder on first or second argument of this function.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n >= 3) {
|
||||||
|
if (a === _) {
|
||||||
|
if (b === _) return curry2((a, b, d, e) => fn(a, b, c, d, e));
|
||||||
|
return curry1((a, d, e) => fn(a, b, c, d, e));
|
||||||
|
}
|
||||||
|
if (b === _) return curry1((b, d, e) => fn(a, b, c, d, e));
|
||||||
|
return fn(a, b, c, d, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n === 2) {
|
||||||
|
if (a === _) return curry2((a, c, d, e) => fn(a, b, c, d, e));
|
||||||
|
return curry1((c, d, e) => fn(a, b, c, d, e));
|
||||||
|
}
|
||||||
|
|
||||||
if (n >= 3) return fn(a, b, c, d, e);
|
|
||||||
if (n === 2) return curry1((c, d, e) => fn(a, b, c, d, e));
|
|
||||||
if (n === 1) return curry2((b, c, d, e) => fn(a, b, c, d, e));
|
if (n === 1) return curry2((b, c, d, e) => fn(a, b, c, d, e));
|
||||||
|
|
||||||
return curried;
|
return curried;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function curry4(fn) {
|
export function curry4(fn) {
|
||||||
return function curried(a, b, c, d, e, f) {
|
return function curried(a, b, c, d, e, f) {
|
||||||
const n = arguments.length;
|
const n = countArguments(arguments, 4);
|
||||||
|
|
||||||
|
if (d === _ || e === _ || f === _) {
|
||||||
|
throw new Error('Can only use placeholder on first, second or third argument of this function.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n >= 4) {
|
||||||
|
if (a === _) {
|
||||||
|
if (b === _) {
|
||||||
|
if (c === _) return curry3((a, b, c, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return curry2((a, b, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
if (c === _) return curry2((a, c, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return curry1((a, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
if (b === _) {
|
||||||
|
if (c === _) return curry2((b, c, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return curry1((b, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
if (c === _) return curry1((c, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return fn(a, b, c, d, e, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n === 3) {
|
||||||
|
if (a === _) {
|
||||||
|
if (b === _) return curry3((a, b, d, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return curry2((a, d, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
if (b === _) return curry2((b, d, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return curry1((d, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n === 2) {
|
||||||
|
if (a === _) return curry3((a, c, d, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
return curry2((c, d, e, f) => fn(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
|
||||||
if (n >= 4) return fn(a, b, c, d, e, f);
|
|
||||||
if (n === 3) return curry1((d, e, f) => fn(a, b, c, d, e, f));
|
|
||||||
if (n === 2) return curry2((c, d, e, f) => fn(a, b, c, d, e, f));
|
|
||||||
if (n === 1) return curry3((b, c, d, e, f) => fn(a, b, c, d, e, f));
|
if (n === 1) return curry3((b, c, d, e, f) => fn(a, b, c, d, e, f));
|
||||||
return curried;
|
return curried;
|
||||||
};
|
};
|
||||||
|
@ -3,12 +3,12 @@ const Benchmark = require('benchmark');
|
|||||||
|
|
||||||
const u = require('../lib');
|
const u = require('../lib');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { curry2 } = require('../lib/util/curry');
|
const { curry4 } = require('../lib/util/curry');
|
||||||
|
|
||||||
const add = (x, y) => x + y;
|
const add = (a, b, c, d) => a + b + c + d;
|
||||||
const fakeCurryAdd = x => y => x + y;
|
const fakeCurryAdd = x => y => x + y;
|
||||||
const curryAdd = _.curry(add);
|
const curryAdd = _.curry(add);
|
||||||
const updeepCurry = curry2(add);
|
const updeepCurry = curry4(add);
|
||||||
// const updeepCurryBig = curry.curryBig(add);
|
// const updeepCurryBig = curry.curryBig(add);
|
||||||
|
|
||||||
const array = [0, 1, 2, 3, 4, 5];
|
const array = [0, 1, 2, 3, 4, 5];
|
||||||
@ -44,8 +44,8 @@ function createSuite(suiteName, tests) {
|
|||||||
|
|
||||||
|
|
||||||
const curryVsLodash = createSuite('Curry', {
|
const curryVsLodash = createSuite('Curry', {
|
||||||
'updeep curry partial call': () => updeepCurry(3)(4),
|
'updeep curry partial call': () => updeepCurry(3)(4)(5)(6),
|
||||||
'lodash curry partial call': () => curryAdd(3)(4),
|
'lodash curry partial call': () => curryAdd(3)(4)(5)(6),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapVsLodash = createSuite('Map', {
|
const mapVsLodash = createSuite('Map', {
|
||||||
@ -66,6 +66,6 @@ const applyVsDestructure = createSuite('apply vs destructure', {
|
|||||||
'destructure': () => fnDestructure(1, 2, 3, 4, 5),
|
'destructure': () => fnDestructure(1, 2, 3, 4, 5),
|
||||||
});
|
});
|
||||||
|
|
||||||
// curryVsLodash();
|
curryVsLodash();
|
||||||
// mapVsLodash();
|
mapVsLodash();
|
||||||
applyVsDestructure();
|
// applyVsDestructure();
|
||||||
|
@ -110,4 +110,12 @@ describe('updeep', () => {
|
|||||||
it('assigns null values', () => {
|
it('assigns null values', () => {
|
||||||
expect(u({isNull: null}, {})).to.eql({isNull: null});
|
expect(u({isNull: null}, {})).to.eql({isNull: null});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can use a placeholder to partially apply', () => {
|
||||||
|
function increment(i) { return i + 1; }
|
||||||
|
const updateJoe = u(u._, { name: 'Joe Merrill', age: 21 });
|
||||||
|
const result = updateJoe({ age: increment });
|
||||||
|
|
||||||
|
expect(result).to.eql({ name: 'Joe Merrill', age: 22 });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { curry1, curry2, curry3, curry4 } from '../../lib/util/curry';
|
import { curry1, curry2, curry3, curry4, _ } from '../../lib/util/curry';
|
||||||
|
|
||||||
describe('curry1', () => {
|
describe('curry1', () => {
|
||||||
it('can curry one arguments', () => {
|
it('can curry one arguments', () => {
|
||||||
@ -26,12 +26,17 @@ describe('curry2', () => {
|
|||||||
const curried = curry2((a, b, c, d) => [a, b, c, d]);
|
const curried = curry2((a, b, c, d) => [a, b, c, d]);
|
||||||
expect(curried(1, 2, 3, 4, 5)).to.eql([1, 2, 3, 4]);
|
expect(curried(1, 2, 3, 4, 5)).to.eql([1, 2, 3, 4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can use the placeholder', () => {
|
||||||
|
const curried = curry2((a, b, c, d) => [a, b, c, d]);
|
||||||
|
expect(curried(_, 2)(1, 3, 4)).to.eql([1, 2, 3, 4]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('curry3', () => {
|
describe('curry3', () => {
|
||||||
it('can curry three arguments', () => {
|
it('can curry three arguments', () => {
|
||||||
const add = curry3((x, y, z) => x + y + z);
|
const add = curry3((x, y, z) => x + y + z);
|
||||||
expect(add(3)(4)(5)).to.equal(12);
|
expect(add(3, _)(4)(5)).to.equal(12);
|
||||||
expect(add()(3)()(4, 5)).to.equal(12);
|
expect(add()(3)()(4, 5)).to.equal(12);
|
||||||
expect(add(3, 4, 5)).to.equal(12);
|
expect(add(3, 4, 5)).to.equal(12);
|
||||||
});
|
});
|
||||||
@ -40,12 +45,20 @@ describe('curry3', () => {
|
|||||||
const curried = curry3((a, b, c, d, e) => [a, b, c, d, e]);
|
const curried = curry3((a, b, c, d, e) => [a, b, c, d, e]);
|
||||||
expect(curried(1, 2, 3, 4, 5, 6)).to.eql([1, 2, 3, 4, 5]);
|
expect(curried(1, 2, 3, 4, 5, 6)).to.eql([1, 2, 3, 4, 5]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can use the placeholder', () => {
|
||||||
|
const curried = curry3((a, b, c, d, e) => [a, b, c, d, e]);
|
||||||
|
expect(curried(_, 2)('a', 3, 4, 5)).to.eql(['a', 2, 3, 4, 5]);
|
||||||
|
expect(curried('b', _, 3)(2, 4, 5)).to.eql(['b', 2, 3, 4, 5]);
|
||||||
|
expect(curried(_, 2, 3)('c', 4, 5)).to.eql(['c', 2, 3, 4, 5]);
|
||||||
|
expect(curried(_, _, 3)('d', 2, 4, 5)).to.eql(['d', 2, 3, 4, 5]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('curry4', () => {
|
describe('curry4', () => {
|
||||||
it('can curry four arguments', () => {
|
it('can curry four arguments', () => {
|
||||||
const add = curry4((x, y, z, u) => x + y + z + u);
|
const add = curry4((x, y, z, u) => x + y + z + u);
|
||||||
expect(add(3)(4)(5)(6)).to.equal(18);
|
expect(add(3, _)(4)(5)(6)).to.equal(18);
|
||||||
expect(add()(3)()(4, 5, 6)).to.equal(18);
|
expect(add()(3)()(4, 5, 6)).to.equal(18);
|
||||||
expect(add(3, 4, 5, 6)).to.equal(18);
|
expect(add(3, 4, 5, 6)).to.equal(18);
|
||||||
});
|
});
|
||||||
@ -54,4 +67,24 @@ describe('curry4', () => {
|
|||||||
const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f]);
|
const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f]);
|
||||||
expect(curried(1, 2, 3, 4, 5, 6, 7)).to.eql([1, 2, 3, 4, 5, 6]);
|
expect(curried(1, 2, 3, 4, 5, 6, 7)).to.eql([1, 2, 3, 4, 5, 6]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can use the placeholder', () => {
|
||||||
|
const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f]);
|
||||||
|
expect(curried(_, 2)('a', 3, 4, 5, 6)).to.eql(['a', 2, 3, 4, 5, 6]);
|
||||||
|
expect(curried(_, 2, 3)('b', 4, 5, 6)).to.eql(['b', 2, 3, 4, 5, 6]);
|
||||||
|
expect(curried(_, 2, 3, 4)('c', 5, 6)).to.eql(['c', 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(curried('d', _, 3)(2, 4, 5, 6)).to.eql(['d', 2, 3, 4, 5, 6]);
|
||||||
|
expect(curried('e', _, 3, 4)(2, 5, 6)).to.eql(['e', 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(curried('f', 2, _, 4)(3, 5, 6)).to.eql(['f', 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(curried(_, _, 3)('g', 2, 4, 5, 6)).to.eql(['g', 2, 3, 4, 5, 6]);
|
||||||
|
expect(curried(_, _, 3, 4)('h', 2, 5, 6)).to.eql(['h', 2, 3, 4, 5, 6]);
|
||||||
|
expect(curried(_, 2, _, 4)('i', 3, 5, 6)).to.eql(['i', 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(curried('j', _, _, 4)(2, 3, 5, 6)).to.eql(['j', 2, 3, 4, 5, 6]);
|
||||||
|
|
||||||
|
expect(curried(_, _, _, 4)('k', 2, 3, 5, 6)).to.eql(['k', 2, 3, 4, 5, 6]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user