Let's start backwards. Say you want a function traceSum
:
> traceSum([1, 2, 3]);
[1, 2, 3]
[2, 3]
[3]
[]
6
You could implement traceSum
as follows:
function traceSum(a) {
console.log(a);
if (a.length === 0) return 0;
else return a[0] + traceSum(a.slice(1));
}
From this implementation we can create a generalized trace
function:
function trace(f) {
return function (a) {
console.log(a);
return f(trace(f), a);
};
}
This is similar to the way the Y combinator is implemented in JavaScript:
function y(f) {
return function (a) {
return f(y(f), a);
};
}
Your traceSum
function can now be implemented as:
var traceSum = trace(function (traceSum, a) {
if (a.length === 0) return 0;
else return a[0] + traceSum(a.slice(1));
});
Unfortunately if you can't modify the sum
function then you can't trace
it since you need some way to specify which function to callback dynamically. Consider:
function sum(a) {
if (a.length === 0) return 0;
else return a[0] + sum(a.slice(1));
}
You cannot trace
the above function because inside the function sum
will always refer to the function itself. There's no way to specify the value of sum
dynamically.