Ramda Adjunct 2.30.0

reduceRightP.js

  1. import { curryN, pipe, equals, reduceRight, length, concat } from 'ramda';
  2. import isUndefined from './isUndefined';
  3. import resolveP from './resolveP';
  4. import allP from './allP';
  5. // in older ramda versions the order of the arguments is flipped
  6. const flipArgs = pipe(reduceRight(concat, ''), equals('ba'))(['a', 'b']);
  7. /* eslint-disable max-len */
  8. /**
  9. * Given an `Iterable`(arrays are `Iterable`), or a promise of an `Iterable`,
  10. * which produces promises (or a mix of promises and values),
  11. * iterate over all the values in the `Iterable` into an array and
  12. * reduce the array to a value using the given iterator function.
  13. *
  14. * Similar to {@link RA.reduceP|reduceP} except moves through the input list from the right to the left.
  15. * The iterator function receives two values: (value, acc),
  16. * while the arguments' order of reduceP's iterator function is (acc, value).
  17. *
  18. * @func reduceRightP
  19. * @memberOf RA
  20. * @since {@link https://char0n.github.io/ramda-adjunct/1.13.0|v1.13.0}
  21. * @category List
  22. * @typedef MaybePromise = Promise.<*> | *
  23. * @sig ((MaybePromise b, Promise a) -> Promise a) -> MaybePromise a -> MaybePromise [MaybePromise b] -> Promise a
  24. * @param {Function} fn The iterator function. Receives two values, the current element from the list and the accumulator
  25. * @param {*|Promise.<*>} acc The accumulator value
  26. * @param {Array.<*>|Promise.<Array<*|Promise.<*>>>} list The list to iterate over
  27. * @return {Promise} The final, accumulated value
  28. * @see {@link RA.reduceP|reduceP}, {@link http://bluebirdjs.com/docs/api/promise.reduce.html|bluebird.reduce}
  29. * @example
  30. *
  31. * RA.reduceRightP(
  32. * (fileName, total) => fs
  33. * .readFileAsync(fileName, 'utf8')
  34. * .then(contents => total + parseInt(contents, 10)),
  35. * 0,
  36. * ['file1.txt', 'file2.txt', 'file3.txt']
  37. * ); // => Promise(10)
  38. *
  39. * RA.reduceRightP(
  40. * (fileName, total) => fs
  41. * .readFileAsync(fileName, 'utf8')
  42. * .then(contents => total + parseInt(contents, 10)),
  43. * Promise.resolve(0),
  44. * ['file1.txt', 'file2.txt', 'file3.txt']
  45. * ); // => Promise(10)
  46. *
  47. * RA.reduceRightP(
  48. * (fileName, total) => fs
  49. * .readFileAsync(fileName, 'utf8')
  50. * .then(contents => total + parseInt(contents, 10)),
  51. * 0,
  52. * [Promise.resolve('file1.txt'), 'file2.txt', 'file3.txt']
  53. * ); // => Promise(10)
  54. *
  55. * RA.reduceRightP(
  56. * (fileName, total) => fs
  57. * .readFileAsync(fileName, 'utf8')
  58. * .then(contents => total + parseInt(contents, 10)),
  59. * 0,
  60. * Promise.resolve([Promise.resolve('file1.txt'), 'file2.txt', 'file3.txt'])
  61. * ); // => Promise(10)
  62. *
  63. */
  64. /* esline-enable max-len */
  65. const reduceRightP = curryN(3, (fn, acc, list) =>
  66. resolveP(list).then((iterable) => {
  67. const listLength = length(iterable);
  68. if (listLength === 0) {
  69. return acc;
  70. }
  71. const reducer = reduceRight((arg1, arg2) => {
  72. let accP;
  73. let currentValueP;
  74. if (flipArgs) {
  75. [accP, currentValueP] = [arg1, arg2];
  76. } else {
  77. [accP, currentValueP] = [arg2, arg1];
  78. }
  79. return accP
  80. .then((previousValue) => allP([previousValue, currentValueP]))
  81. .then(([previousValue, currentValue]) => {
  82. if (isUndefined(previousValue) && listLength === 1) {
  83. return currentValue;
  84. }
  85. return fn(currentValue, previousValue);
  86. });
  87. });
  88. return reducer(resolveP(acc), iterable);
  89. })
  90. );
  91. export default reduceRightP;