在λ演算中,“纯”的含义是指仅包含单参数函数和单参数函数调用的单参数函数。恢复源代码的意思是指变量重命名后的代码与原代码相同。例如,
n2 = function(v0){return function(v1){return v0(v0(v1))}}
console.log(source(n2));
console.log(source(n2(n2)));
应该打印:
function(v0){return function(v0){return v0(v0(v1))}}
function(v0){return function(v0){return v0(v0(v0(v0(v1))))}}
也就是说,第一行显示了函数 n2
的原始来源,而第二行显示了通过评估 n2(n2)
返回的函数的来源。
我已经成功地实现了它,如下所示:
function source(f){
var nextVarId = 0;
return (function recur(f){
if (typeof f === "function"){
if (f.isVarFunc) return f(null);
else {
var varName = "v"+(nextVarId++);
var varFunc = function rec(res){
var varFunc = function(arg){
return arg === null
? "("+res.join(")(")+")"
: rec(res.concat(recur(arg)));
};
varFunc.isVarFunc = true;
return varFunc;
};
varFunc.isVarFunc = true;
var body = f(varFunc([varName]));
body = body.isVarFunc ? body(null) : recur(body);
return "(function("+varName+"){return "+body+"})";
};
} else return f;
})(f);
};
问题在于我使用了一种相当丑陋的方法来标记函数,即将它们的名称设置为特定值,而这种方法不适用于应用多次的函数(例如
a(b)(b)
)。有没有更好的方法来解决这个问题?编辑:我成功设计了一个版本,似乎在所有情况下都是正确的,但它仍然是一个丑陋、难以阅读和缺乏原则性的混乱。
n2(n2)
创建了一个JS闭包函数,而不是折叠函数,因此没有提供对其内部(闭合变量,我的意思是代码不足)的任何访问。当然,你可以编写自己的apply(n2, [n2])
函数来创建正常形式的函数。 - Bergi