From 6b875ea017133022c0aa0d07ffd8058f031874fe Mon Sep 17 00:00:00 2001 From: Pedr Browne Date: Thu, 1 Feb 2018 09:47:21 +0000 Subject: [PATCH] =?UTF-8?q?feat(nonePass):=20Add=20complement=20of=20Ramda?= =?UTF-8?q?=E2=80=99s=20anyPass=20(#327)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref #234 --- src/index.d.ts | 10 ++++++++++ src/index.js | 1 + src/nonePass.js | 33 +++++++++++++++++++++++++++++++++ test/nonePass.js | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 src/nonePass.js create mode 100644 test/nonePass.js diff --git a/src/index.d.ts b/src/index.d.ts index 74ab50fc6d..448019ef10 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -774,6 +774,16 @@ declare namespace RamdaAdjunct { */ notAllPass(predicates: Array): Function; + /** + * Takes a list of predicates and returns a predicate that returns true for a given list of + * arguments if none of the provided predicates are satisfied by those arguments. It is the + * complement of Ramda's anyPass. + * + * The function returned is a curried function whose arity matches that of the + * highest-arity predicate. + */ + nonePass(predicates: Array): Function; + /** * Identity type. */ diff --git a/src/index.js b/src/index.js index 0d807a0bc8..9289758533 100644 --- a/src/index.js +++ b/src/index.js @@ -126,5 +126,6 @@ export { default as defaultWhen } from './defaultWhen'; export { default as notBoth } from './notBoth'; export { default as neither } from './neither'; export { default as notAllPass } from './notAllPass'; +export { default as nonePass } from './nonePass'; // Types export { default as Identity } from './fantasy-land/Identity'; diff --git a/src/nonePass.js b/src/nonePass.js new file mode 100644 index 0000000000..8399863196 --- /dev/null +++ b/src/nonePass.js @@ -0,0 +1,33 @@ +import { complement, compose, anyPass } from 'ramda'; + + +/** + * Takes a list of predicates and returns a predicate that returns true for a given list of + * arguments if none of the provided predicates are satisfied by those arguments. It is the + * complement of Ramda's anyPass. + * + * The function returned is a curried function whose arity matches that of the + * highest-arity predicate. + * + * @func nonePass + * @memberOf RA + * @since {@link https://char0n.github.io/ramda-adjunct/2.5.0|v2.5.0} + * @category Logic + * @sig [(*... -> Boolean)] -> (*... -> Boolean) + * @param {Array} predicates An array of predicates to check + * @return {Function} The combined predicate + * @see {@link http://ramdajs.com/docs/#anyPass|anyPass} + * @example + * + * const gt10 = R.gt(R.__, 10) + * const even = (x) => x % 2 === 0; + * const f = RA.nonePass([gt10, even]); + * + * f(12); //=> false + * f(8); //=> false + * f(11); //=> false + * f(9); //=> true + */ +const nonePass = compose(complement, anyPass); + +export default nonePass; diff --git a/test/nonePass.js b/test/nonePass.js new file mode 100644 index 0000000000..328ec52cf7 --- /dev/null +++ b/test/nonePass.js @@ -0,0 +1,32 @@ +import * as RA from '../src/index'; +import eq from './shared/eq'; + + +describe('nonePass', function () { + const odd = n => n % 2 !== 0; + const divBy3 = n => n % 3 === 0; + const lt20 = n => n < 20; + const plusEq = (w, x, y, z) => w + x === y + z; + + it('reports whether all predicates are satisfied by a given value', function () { + const ok = RA.nonePass([odd, divBy3, lt20]); + eq(ok(9), false); // all ps succeed + eq(ok(12), false); // p1 fails + eq(ok(7), false); // p2 fails + eq(ok(21), false); // p3 fails + eq(ok(2), false); // p1 and p2 fails + eq(ok(18), false); // p1 and p3 fails + eq(ok(23), false); // p2 and p3 fails + eq(ok(26), true); // all ps fail + }); + + it('returns true on empty predicate list', function () { + eq(RA.nonePass([])(3), true); + }); + + it('returns a curried function whose arity matches that of the highest-arity predicate', function () { + eq(RA.nonePass([odd, divBy3, plusEq]).length, 4); + eq(RA.nonePass([odd, divBy3, plusEq])(26, 26, 26, 28), true); + eq(RA.nonePass([odd, divBy3, plusEq])(26)(26)(26)(28), true); + }); +});