柯里化形式的递归函数可以尾递归吗?
Can a recursive function in curried form be tail recursive?
给定以下递归 map
函数:
const U = f => f(f);
const map = f => U(h => acc => ([head, ...tail]) => head === undefined
? acc
: h(h)([...acc, f(head)])(tail))([]);
const xs = [1,2,3,4,5];
console.log(map(x => x * x)([1,2,3,4,5]));
显然,递归调用h(h)
不是递归函数的最后一个动作。但是当堆栈展开时,所发生的一切都是返回完成的累加器而无需任何进一步的更改或操作。 map
是否违背了我的预期尾递归?
the recursive call h(h)
isn't the last action of the recursive function
h(h)
不是递归调用。 …(tail)
是递归调用,是的,它在尾部位置。
如果你放弃那个过于复杂的 U
组合器(或者至少立即使用 Y
组合器),这可能会变得更加明显:
const map = f => {
const mapF = acc => ([head, ...tail]) => head === undefined
? acc
: mapF([...acc, f(head)])(tail);
return mapF([]);
};
给定以下递归 map
函数:
const U = f => f(f);
const map = f => U(h => acc => ([head, ...tail]) => head === undefined
? acc
: h(h)([...acc, f(head)])(tail))([]);
const xs = [1,2,3,4,5];
console.log(map(x => x * x)([1,2,3,4,5]));
显然,递归调用h(h)
不是递归函数的最后一个动作。但是当堆栈展开时,所发生的一切都是返回完成的累加器而无需任何进一步的更改或操作。 map
是否违背了我的预期尾递归?
the recursive call
h(h)
isn't the last action of the recursive function
h(h)
不是递归调用。 …(tail)
是递归调用,是的,它在尾部位置。
如果你放弃那个过于复杂的 U
组合器(或者至少立即使用 Y
组合器),这可能会变得更加明显:
const map = f => {
const mapF = acc => ([head, ...tail]) => head === undefined
? acc
: mapF([...acc, f(head)])(tail);
return mapF([]);
};