In my previous Quesion:
Extracting data from a function chain without arrays
@Aadit M Shah gave me astonishing solution as follows:
https://stackoverflow.com/a/51420884/6440264
Given an expression like A(a)(b)(f)
where f
is a function, it's impossible to know whether f
is supposed to be added to the list or whether it's the reducing function. Hence, I'm going to describe how to write expressions like A(a)(b)(f, x)
which is equivalent to [a, b].reduce(f, x)
. This allows us to distinguish when the list ends depending upon how many arguments you provide:
const L = g => function (x, a) {
switch (arguments.length) {
case 1: return L(k => g((f, a) => k(f, f(a, x))));
case 2: return g((f, a) => a)(x, a);
}
};
const A = L(x => x);
const xs = A(1)(2)(3)(4)(5);
console.log(xs((x, y) => x + y, 0)); // 15
console.log(xs((x, y) => x * y, 1)); // 120
console.log(xs((a, x) => a.concat(x), [])); // [1,2,3,4,5]
It works due to continuations. Every time we add a new element, we accumulate a CPS function. Each CPS function calls the previous CPS function, thereby creating a CPS function chain. When we give this CPS function chain a base function, it unrolls the chain and allows us to reduce it. It's the same idea behind transducers and lenses.
There are 2 issues remained for me.
To distinguish reducing function, I consider some custom Typing mechanism using reflection, but in order to focus on this issue, so far I would like to simply apply
const isReducer = f => (typeof f === 'function');
Requirement to provide an initial value has a limit to fold/reduce, for instance, it's impossible to provide an initial value for binary operations to the reduce such as
const head = (a, b) => a; const tail = (a, b) => b;
(unless you provide the first/last value manually that makes no sense to run the code) In theory, every binary operations has a identity value, but something is impossible to provide as it is. The only way is to abstract as an identity.
Having said that, I can not refactor the provided code to single arguments and by a reducer type of the function, and the default value as the initial value of the sequence.
Can you provide the refactored code? Also any information of transducer/ CPS for this example is appreciated.