UNPKG

rubico

Version:

[a]synchronous functional programming

166 lines (156 loc) 4.57 kB
const promiseAll = require('./_internal/promiseAll') const isPromise = require('./_internal/isPromise') const areAnyValuesPromises = require('./_internal/areAnyValuesPromises') const __ = require('./_internal/placeholder') const curry2 = require('./_internal/curry2') const curry3 = require('./_internal/curry3') const curryArgs2 = require('./_internal/curryArgs2') const thunkConditional = require('./_internal/thunkConditional') const areAllValuesNonfunctions = require('./_internal/areAllValuesNonfunctions') const thunkify2 = require('./_internal/thunkify2') const thunkify3 = require('./_internal/thunkify3') const always = require('./_internal/always') /** * @name areAllValuesTruthy * * @synopsis * ```coffeescript [specscript] * areAllValuesTruthy(predicates Array<value>) -> Promise|boolean * ``` */ const areAllValuesTruthy = function (predicates, index) { const length = predicates.length while (++index < length) { const predicate = predicates[index] if (isPromise(predicate)) { return predicate.then(curry3( thunkConditional, __, thunkify2(areAllValuesTruthy, predicates, index), always(false), )) } if (!predicate) { return false } } return true } /** * @name asyncArePredicatesAllTruthy * * @synopsis * ```coffeescript [specscript] * asyncArePredicatesAllTruthy( * predicates Array<value=>Promise|boolean> * args Array, * index number, * ) -> allTruthy boolean * ``` */ const asyncArePredicatesAllTruthy = async function (args, predicates, index) { const length = predicates.length while (++index < length) { let predicate = predicates[index] if (typeof predicate == 'function') { predicate = predicate(...args) } if (isPromise(predicate)) { predicate = await predicate } if (!predicate) { return false } } return true } // areAllPredicatesTruthy(args Array, predicates Array<function>) -> Promise|boolean const areAllPredicatesTruthy = function (args, predicates) { const length = predicates.length let index = -1 while (++index < length) { let predicate = predicates[index] if (typeof predicate == 'function') { predicate = predicate(...args) } if (isPromise(predicate)) { return predicate.then(curry3( thunkConditional, __, thunkify3(asyncArePredicatesAllTruthy, args, predicates, index), always(false), )) } if (!predicate) { return false } } return true } /** * @name and * * @synopsis * ```coffeescript [specscript] * and(values Array<boolean>) -> result boolean * * and(...args, predicatesOrValues Array<function|boolean>) -> Promise|boolean * * and(predicatesOrValues Array<function|boolean>)(...args) -> Promise|boolean * ``` * * @description * Tests an array of boolean values, returning true if all boolean values are truthy. * * ```javascript [playground] * const oneIsLessThanThree = 1 < 3 * const twoIsGreaterThanOne = 2 > 1 * const threeIsEqualToThree = 3 === 3 * * console.log( * and([oneIsLessThanThree, twoIsGreaterThanOne, threeIsEqualToThree]), * ) // true * ``` * * If any values in the array are synchronous or asynchronous predicate functions, `and` takes another argument to test concurrently against the predicate functions, returning true if all array values and resolved values from the predicates are truthy. * * ```javascript [playground] * const isOdd = number => number % 2 == 1 * * const isPositive = number => number > 0 * * const isLessThan3 = number => number < 3 * * console.log( * and([isOdd, isPositive, isLessThan3])(1), * ) // true * ``` * * Any promises passed in argument position are resolved for their values before further execution. This only applies to the eager version of the API. * * ```javascript [playground] * and(Promise.resolve(5), [ * n => n > 0, * n => n < 10, * ]).then(console.log) // true * ``` * * @execution series * * @note ...args slows down here by an order of magnitude */ const and = function (...args) { const predicatesOrValues = args.pop() if (areAllValuesNonfunctions(predicatesOrValues)) { return areAllValuesTruthy(predicatesOrValues, -1) } if (args.length == 0) { return curryArgs2(areAllPredicatesTruthy, __, predicatesOrValues) } if (areAnyValuesPromises(args)) { return promiseAll(args) .then(curry2(areAllPredicatesTruthy, __, predicatesOrValues)) } return areAllPredicatesTruthy(args, predicatesOrValues) } module.exports = and