[d24f17c] | 1 | import {
|
---|
| 2 | sort,
|
---|
| 3 | comparator,
|
---|
| 4 | prop,
|
---|
| 5 | pipe,
|
---|
| 6 | head,
|
---|
| 7 | curryN,
|
---|
| 8 | reduce,
|
---|
| 9 | reduced,
|
---|
| 10 | curry,
|
---|
| 11 | ifElse,
|
---|
| 12 | } from 'ramda';
|
---|
| 13 |
|
---|
| 14 | /**
|
---|
| 15 | * Can be used as a way to compose multiple invokers together to form polymorphic functions,
|
---|
| 16 | * or functions that exhibit different behaviors based on their argument(s).
|
---|
| 17 | * Consumes dispatching functions and keep trying to invoke each in turn, until a non-nil value is returned.
|
---|
| 18 | *
|
---|
| 19 | * Accepts a list of dispatching functions and returns a new function.
|
---|
| 20 | * When invoked, this new function is applied to some arguments,
|
---|
| 21 | * each dispatching function is applied to those same arguments until one of the
|
---|
| 22 | * dispatching functions returns a non-nil value.
|
---|
| 23 | *
|
---|
| 24 | * @func dispatch
|
---|
| 25 | * @memberOf RA
|
---|
| 26 | * @since {@link https://char0n.github.io/ramda-adjunct/2.6.0|v2.6.0}
|
---|
| 27 | * @category Function
|
---|
| 28 | * @sig [((a, b, ...) -> x1), ((a, b, ...) -> x2), ...] -> x1 | x2 | ...
|
---|
| 29 | * @param {!Array} functions A list of functions
|
---|
| 30 | * @return {*|undefined} Returns the first not-nil value, or undefined if either an empty list is provided or none of the dispatching functions returns a non-nil value
|
---|
| 31 | * @see {@link RA.isNotNil}
|
---|
| 32 | * @example
|
---|
| 33 | *
|
---|
| 34 | * // returns first non-nil value
|
---|
| 35 | * const stubNil = () => null;
|
---|
| 36 | * const stubUndefined = () => undefined;
|
---|
| 37 | * const addOne = v => v + 1;
|
---|
| 38 | * const addTwo = v => v + 2;
|
---|
| 39 | *
|
---|
| 40 | * RA.dispatch([stubNil, stubUndefined, addOne, addTwo])(1); //=> 2
|
---|
| 41 | *
|
---|
| 42 | * // acts as a switch
|
---|
| 43 | * const fnSwitch = RA.dispatch([
|
---|
| 44 | * R.ifElse(RA.isString, s => `${s}-join`, RA.stubUndefined),
|
---|
| 45 | * R.ifElse(RA.isNumber, n => n + 1, RA.stubUndefined),
|
---|
| 46 | * R.ifElse(RA.isDate, R.T, RA.stubUndefined),
|
---|
| 47 | * ]);
|
---|
| 48 | * fnSwitch(1); //=> 2
|
---|
| 49 | */
|
---|
| 50 | import isNotNil from './isNotNil';
|
---|
| 51 | import isNonEmptyArray from './isNonEmptyArray';
|
---|
| 52 | import stubUndefined from './stubUndefined';
|
---|
| 53 |
|
---|
| 54 | const byArity = comparator((a, b) => a.length > b.length);
|
---|
| 55 |
|
---|
| 56 | const getMaxArity = pipe(sort(byArity), head, prop('length'));
|
---|
| 57 |
|
---|
| 58 | const iteratorFn = curry((args, accumulator, fn) => {
|
---|
| 59 | const result = fn(...args);
|
---|
| 60 |
|
---|
| 61 | return isNotNil(result) ? reduced(result) : accumulator;
|
---|
| 62 | });
|
---|
| 63 |
|
---|
| 64 | const dispatchImpl = (functions) => {
|
---|
| 65 | const arity = getMaxArity(functions);
|
---|
| 66 |
|
---|
| 67 | return curryN(arity, (...args) =>
|
---|
| 68 | reduce(iteratorFn(args), undefined, functions)
|
---|
| 69 | );
|
---|
| 70 | };
|
---|
| 71 |
|
---|
| 72 | const dispatch = ifElse(isNonEmptyArray, dispatchImpl, stubUndefined);
|
---|
| 73 |
|
---|
| 74 | export default dispatch;
|
---|