Skip to content

Commit

Permalink
feat: implement any
Browse files Browse the repository at this point in the history
  • Loading branch information
customcommander committed Oct 27, 2021
1 parent 0530a94 commit 077261e
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 27 deletions.
3 changes: 2 additions & 1 deletion src/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ module.exports = {
* @param {function(?): boolean} pred Predicate
* @param {Array|Object|string} xs List of values
* @returns {boolean}
* @see any
* @see none
*/
all: curry((pred, xs) => {
for (let [_, v] of iter(xs)) if (pred(v) !== true) return false;
return true;
})
};
};
45 changes: 45 additions & 0 deletions src/any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @license MIT
* @copyright (c) 2021 Julien Gonzalez <hello@spinjs.com>
*/

const iter = require('./_iterable');
const {curry} = require('./curry');

/**
* @namespace
* @alias ROOT
*/
module.exports = {
/**
* True if one element of `xs` did satisfy predicate `pred`.
* False if none did.
*
* @example
* > Check that a list does contain at least one 'x'
*
* ```javascript
* const has_x = any(x => x === 'x');
*
* has_x(['a','b','c']); //=>false
* has_x(['a','x','c']); //=> true
*
* has_x('abc'); //=> false
* has_x('axc'); //=> true
*
* has_x({m: 'a', n: 'b', o: 'c'}); //=> false
* has_x({m: 'a', n: 'x', o: 'c'}); //=> true
* ```
*
* @public
* @param {function(?): boolean} pred Predicate
* @param {Array|Object|string} xs List of values
* @returns {boolean}
* @see all
* @see none
*/
any: curry((pred, xs) => {
for (let [_, v] of iter(xs)) if (pred(v) === true) return true;
return false;
})
};
53 changes: 27 additions & 26 deletions src/none.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,34 @@ const {curry} = require('./curry');
*/
module.exports = {
/**
* True if all elements of `xs` didn't satisfy predicate `pred`.
* Otherwise returns false as soon as one did.
*
* @example
* > Check that a list does not contain any 'x'
*
* ```javascript
* const no_x = none(x => x === 'x');
*
* no_x(['a','b','c']); //=> true
* no_x(['a','x','c']); //=> false
*
* no_x('abc'); //=> true
* no_x('axc'); //=> false
*
* no_x({m: 'a', n: 'b', o: 'c'}); //=> true
* no_x({m: 'a', n: 'x', o: 'c'}); //=> false
* ```
*
* @public
* @param {function(?): boolean} pred Predicate
* @param {Array|Object|string} xs List of values
* @returns {boolean}
* @see all
*/
* True if all elements of `xs` didn't satisfy predicate `pred`.
* Otherwise returns false as soon as one did.
*
* @example
* > Check that a list does not contain any 'x'
*
* ```javascript
* const no_x = none(x => x === 'x');
*
* no_x(['a','b','c']); //=> true
* no_x(['a','x','c']); //=> false
*
* no_x('abc'); //=> true
* no_x('axc'); //=> false
*
* no_x({m: 'a', n: 'b', o: 'c'}); //=> true
* no_x({m: 'a', n: 'x', o: 'c'}); //=> false
* ```
*
* @public
* @param {function(?): boolean} pred Predicate
* @param {Array|Object|string} xs List of values
* @returns {boolean}
* @see all
* @see any
*/
none: curry((pred, xs) => {
for (let [_, v] of iter(xs)) if (pred(v) === true) return false;
return true;
})
};
};
66 changes: 66 additions & 0 deletions test/any.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const td = require('testdouble');
const test = require('tape');
const {any: sut} = require('..');

test('any(pred)(xs) -> false when xs is empty', t => {
const f = td.func();
t.same(sut(f)([]), false);
t.same(sut(f)(""), false);
t.same(sut(f)({}), false);
td.verify(f(), {times: 0, ignoreExtraArgs: true});
t.end();
});

test('any(pred)(xs) -> true if pred(x) returned true for one x of xs', t => {
const f = td.func();
const g = td.func();
const h = td.func();
td.when(f(1)).thenReturn(true);
td.when(g(4)).thenReturn(true);
td.when(h("🥑")).thenReturn(true);
t.same(sut(f)([1, 2]), true);
t.same(sut(g)({a: 4, b: 5}), true);
t.same(sut(h)("🥑🌯"), true);
td.verify(f(), {times: 1, ignoreExtraArgs: true});
td.verify(g(), {times: 1, ignoreExtraArgs: true});
td.verify(h(), {times: 1, ignoreExtraArgs: true});
t.end();
});

test('any(pred)(xs) -> false even if pred(x) returned truthy for all x of xs', t => {
const f = td.func();
const g = td.func();
const h = td.func();
td.when(f(1)).thenReturn(1);
td.when(f(2)).thenReturn('true');
td.when(g(4)).thenReturn([]);
td.when(g(5)).thenReturn([true]);
td.when(h("🥑")).thenReturn(10);
td.when(h("🌯")).thenReturn(20);
t.same(sut(f)([1, 2]), false);
t.same(sut(g)({a: 4, b: 5}), false);
t.same(sut(h)("🥑🌯"), false);
td.verify(f(), {times: 2, ignoreExtraArgs: true});
td.verify(g(), {times: 2, ignoreExtraArgs: true});
td.verify(h(), {times: 2, ignoreExtraArgs: true});
t.end();
});

test('any(pred)(xs) -> false if pred(x) returned false for all x of xs', t => {
const f = td.func();
const g = td.func();
const h = td.func();
td.when(f(1)).thenReturn(false);
td.when(f(2)).thenReturn(false);
td.when(g(4)).thenReturn(false);
td.when(g(5)).thenReturn(false);
td.when(h("🥑")).thenReturn(false);
td.when(h("🌯")).thenReturn(false);
t.same(sut(f)([1, 2]), false);
t.same(sut(g)({a: 4, b: 5}), false);
t.same(sut(h)("🥑🌯"), false);
td.verify(f(), {times: 2, ignoreExtraArgs: true});
td.verify(g(), {times: 2, ignoreExtraArgs: true});
td.verify(h(), {times: 2, ignoreExtraArgs: true});
t.end();
});

0 comments on commit 077261e

Please sign in to comment.