src/optic_array.js

  1. import Optic from './optic.js';
  2. import { isLens, lensCap } from './utils.js';
  3. /**
  4. * @extends Optic
  5. */
  6. class OpticArray extends Optic {
  7. /**
  8. * @summary Aggregation of multiple lens applied in series
  9. *
  10. * @description
  11. * Construct this using {@link module:natural-lenses#fuse}.
  12. */
  13. constructor(lenses) {
  14. super();
  15. this.lenses = lenses;
  16. }
  17. /**
  18. * @inheritdoc
  19. */
  20. present(subject) {
  21. if (this.lenses.length === 0) return true;
  22. const throughLenses = this.lenses.slice(), finalLens = throughLenses.pop();
  23. const rval = throughLenses.reduce(
  24. (subject, lens) => lens.get(subject),
  25. subject
  26. );
  27. return finalLens.present(rval);
  28. }
  29. /**
  30. * @inheritdoc
  31. */
  32. get(subject, ...tail) {
  33. const subjResult = Array.prototype.reduce.call(
  34. this.lenses,
  35. (subject, lens) => lens.get(subject),
  36. subject
  37. );
  38. if (tail.length > 0) {
  39. return isLens(subjResult) ? subjResult.get(...tail) : undefined
  40. }
  41. return subjResult;
  42. }
  43. /**
  44. * @inheritdoc
  45. */
  46. get_maybe(subject, ...tail) {
  47. const stepSubject = get_maybe_internal.call(this, {just: subject});
  48. const subjResult = stepSubject.just;
  49. if (tail.length > 0) {
  50. return isLens(subjResult) ? subjResult.get_maybe(...tail) : {};
  51. }
  52. return stepSubject;
  53. }
  54. /**
  55. * @inheritdoc
  56. */
  57. xformInClone_maybe(subject, fn) {
  58. var i;
  59. const lensSubjects = new Array(this.lenses.length);
  60. lensSubjects[0] = {just: subject};
  61. const leadingLensCount = this.lenses.length - 1;
  62. for (i = 0; i < leadingLensCount; i++) {
  63. const l = this.lenses[i];
  64. lensSubjects[i + 1] = l.get_maybe(lensSubjects[i].just);
  65. if (!('just' in lensSubjects[i + 1])) {
  66. break;
  67. }
  68. }
  69. const xformResults = new Array(this.lenses.length);
  70. i = this.lenses.length - 1;
  71. const xformInput_maybe = (lensSubjects[i] || {});
  72. xformResults[i] = this.lenses[i].xformInClone_maybe(xformInput_maybe.just, fn);
  73. if ('just' in xformInput_maybe) {
  74. if (xformResults[i] === xformInput_maybe.just) {
  75. return subject;
  76. }
  77. }
  78. for (i = leadingLensCount - 1; i >= 0; i--) {
  79. let lensSubject = lensSubjects[i] || {};
  80. xformResults[i] = this.lenses[i].setInClone(lensSubject.just, xformResults[i + 1]);
  81. }
  82. return xformResults[0];
  83. }
  84. }
  85. export default OpticArray;
  86. /**
  87. * @private
  88. * @this OpticArray
  89. * @param {Maybe.<*>} subject_maybe
  90. * @returns {Maybe.<*>}
  91. */
  92. function get_maybe_internal(subject_maybe) {
  93. let stepSubject = subject_maybe;
  94. for (let i = 0; i < this.lenses.length; i++) {
  95. const lens = this.lenses[i];
  96. stepSubject = lens.get_maybe(stepSubject.just);
  97. if (!('just' in stepSubject)) {
  98. return {};
  99. }
  100. }
  101. return stepSubject;
  102. }