Is there some way to "wrap" a recursive function via a higher-order function, so that the recursive call is also wrapped? (e.g. to log the arguments to the function on each call.)
For example, suppose we have a function, sum()
, that returns the sum of a list of numbers by adding the head to the sum of the tail:
function sum(a) {
if (a.length === 0) {
return 0;
} else {
return a[0] + sum(a.slice(1));
}
}
Is there some way to write a higher-order function, logging()
, that takes the sum()
function as input, and returns a function that outputs the arguments to sum()
on each recursive call?
The following does not work:
function logging(fn) {
return function(a) {
console.log(a);
return fn(a);
}
}
sum2 = logging(sum);
sum2([1, 2, 3]);
Actual output:
[1, 2, 3]
-> 6
Expected output:
[1, 2, 3]
[2, 3]
[3]
[]
-> 6
Is this even possible if sum()
is rewritten so that it can be used with Y Combinator-style "recursion"?
function sum_core(g) {
return function (a) {
if (a.length === 0) {
return 0;
} else {
return a[0] + g(a.slice(1));
}
};
}
sum = Y(sum_core);
sum([1, 2, 3]);
// -> 6
Let's start backwards. Say you want a function
traceSum
:You could implement
traceSum
as follows:From this implementation we can create a generalized
trace
function:This is similar to the way the Y combinator is implemented in JavaScript:
Your
traceSum
function can now be implemented as:Unfortunately if you can't modify the
sum
function then you can'ttrace
it since you need some way to specify which function to callback dynamically. Consider:You cannot
trace
the above function because inside the functionsum
will always refer to the function itself. There's no way to specify the value ofsum
dynamically.