【发布时间】:2015-10-12 22:38:32
【问题描述】:
我所说的 Pure 是指 λ 演算的意义,即,除了单参数函数和单参数函数调用之外,它的主体上不包含任何内容的单参数函数。通过恢复源代码,我的意思是变量重命名。所以,例如,
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))。有没有更好的原则性方法来解决这个问题?
编辑:我设法设计了一个似乎在所有情况下都是正确的版本,但它仍然是一个丑陋的无法阅读的无原则的混乱。
【问题讨论】:
-
闭包不是这样工作的。创建了对封闭范围的引用,代码保持不变。
-
你可能更想在 JS 中实现自己的 lambda 演算解释器(它并不复杂),而不是弄乱 JS 函数和 JS 代码。
-
代码的重点是强制 V8 引擎将 JavaScript 函数评估为正常形式,这意味着每个闭包都会崩溃。
-
我已经在 JavaScript 上编写了几个 lambda 演算解释器,实际上,包括一个比 V8 本身(Optlam)渐近更快的解释器,但在许多情况下,你根本无法让解释器运行得比原生函数快,所以我特别需要我问的。
-
您的问题是
n2(n2)确实创建了一个 JS 闭包函数,而不是折叠函数,因此不提供对其内部的任何访问(封闭变量,我的意思是代码是不足够的)。您当然可以编写自己的apply(n2, [n2])函数来创建正常形式的函数。
标签: javascript functional-programming lambda-calculus