有没有办法在JavaScript中模拟内联let表达式?
我正在编写一个从函数式语言到JavaScript的编译器。因为我的语言是基于表达式的,所以将其编译为JavaScript表达式也是很自然的。问题是,在编译有没有办法在JavaScript中模拟内联let表达式?,javascript,Javascript,我正在编写一个从函数式语言到JavaScript的编译器。因为我的语言是基于表达式的,所以将其编译为JavaScript表达式也是很自然的。问题是,在编译let表达式时,我们需要能够“内联”声明和分配变量。例如: function foo(x) { return (let y = x * x; y); } 显然,这段代码不起作用,因为我们不能在表达式中使用let。一种解决方案是将所有内容包装在lambda中: function foo(x) { return (()=>{let
let
表达式时,我们需要能够“内联”声明和分配变量。例如:
function foo(x) {
return (let y = x * x; y);
}
显然,这段代码不起作用,因为我们不能在表达式中使用let
。一种解决方案是将所有内容包装在lambda中:
function foo(x) {
return (()=>{let y = x*x; return y})();
}
但在某些情况下,这会带来巨大的运行时成本。另一种选择是调整编译器以生成语句而不是表达式,但这将是一个非常重要的更改,如果可能的话,我宁愿避免
有没有办法将局部变量作为表达式而不是没有额外运行时开销的语句声明并分配给JavaScript
有没有办法将局部变量作为表达式而不是没有额外运行时开销的语句声明并分配给JavaScript
不是真的,但你可以用。我知道,我知道,eval()
是邪恶的,但这是在表达式(AFAIK)中声明local变量的唯一方法,尽管我不推荐它,因为引擎不会优化eval()
调用
函数foo(x){
收益(评估(“var y”),y=x*x,y);
}
编辑:如前所述,使用let
使变量成为使用eval()
执行的内部代码的局部变量,从而导致y=x*x
创建一个名为y
的全局变量<代码>变量应改为使用。不,没有
您应该考虑使用标准lambda演算技术,其中<代码> x=………<代码>相当于<代码>(x= >…)(…)< /代码>。然后让编译器再次运行,删除多余的函数表达式,尽可能地引入语句
另一种方法可能是使用中的
do{let x=…;…}
语法,允许您使用生成无函数代码。您应该避免创建新变量,只需直接返回值:
function foo(x) {
return x * x;
}
但是,如果您确实需要内联let,这应该是可行的:
const foo = (x) => {let y=x*x;return y;}
真正的lambda版本应该是
return(y=>y)(x*x)代码>为了简化,这可能也更容易进行后处理。为什么不使用函数foo(x){return x*x}
这是一个很好的选择,但也有很大的运行时成本,不幸的是,特别是在非常数字的代码中。我不知道为什么JS运行时不能优化它,因为它只是一个内联的步骤,但它就是这样。@ EpasCall Load考虑一个函数,如“代码> POW2(x){返回(让y=POW2(x-1);x==0?1:y+y);}。如果我们按照您的建议删除let
,我将成为pow2(x){return x==0?1:pow2(x-1)+pow2(x-1);}
。请注意,第一个函数是O(n)
,第二个函数是O(2^n)
。在某些情况下,这样做可能会导致指数减速。嘿,这是一个我没有想到的有趣的解决方案。当然,这并不能解决这个问题,因为一个额外的函数调用将比在每个let
上调用eval
要快得多,但您可以从中获得创新点。实际上,这确实声明了一个全局变量(出于某些我还不太了解的原因),在严格模式下,它肯定会失败,let
-声明的变量受eval
ed表达式中的局部作用域约束。@Bergi我发现了问题并编辑了我的答案。谢谢。@D.Pardal哦,当然,创建全局变量的不是让y
全局求值,而是在草率模式下的y=…
赋值。谢谢你的更新。但是请注意,即使是var
也不能在严格模式下工作。