【问题标题】:Is there any way to emulate inline let expressions in JavaScript?有没有办法在 JavaScript 中模拟内联 let 表达式?
【发布时间】:2020-06-01 20:09:05
【问题描述】:

我正在编写一个从函数式语言到 JavaScript 的编译器。由于我的语言是基于表达式的,因此很自然地将其编译为 JavaScript 表达式。问题是在编译let 表达式时,我们需要能够“内联”声明和分配变量。例如:

function foo(x) {
  return (let y = x * x; y);
}

显然,这段代码不起作用,因为我们不能在表达式中使用let。一种解决方案是将所有内容包装在 lambda 中:

function foo(x) {
  return (()=>{let y = x*x; return y})();
} 

但这在某些情况下会产生巨大的运行时成本。另一种选择是仅调整编译器以生成语句而不是表达式,但这将是一个重要的更改,如果可能的话我宁愿避免它。

有什么方法可以将局部变量作为表达式而不是没有额外运行时成本的语句声明和分配给 JavaScript?

【问题讨论】:

  • 真正的 lambda 版本是 return (y => y)(x * x); 这可能也更容易后处理以简化。
  • 为什么不只是function foo (x) { return x*x }
  • 这是一个很好的选择,但遗憾的是,它也有很大的运行时成本,特别是在非常数字的代码中。我不确定为什么 JS 运行时不能优化它,因为它只是一个内联步骤,但事实就是这样。
  • @epascarello 考虑像pow2(x) { return (let 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)。在某些情况下,这样做可能会导致指数级减速。

标签: javascript


【解决方案1】:

不,没有。

您应该考虑使用标准 lambda 演算技术,其中 let x = … in … 等效于 (x => …)(…)。然后让你的编译器再一次通过删除多余的函数表达式,尽可能引入语句。

另一种方法可能是使用do expressions proposal 中的do { let x = …; … } 语法,允许您使用their transpiler plugin 生成无功能代码。

【讨论】:

    【解决方案2】:

    您应该避免创建新变量而直接返回值:

    function foo(x) {
      return  x * x;
    }
    

    但如果你真的需要内联一个 let,这应该可行:

    const foo = (x) => {let y=x*x;return y;}
    

    【讨论】:

      【解决方案3】:

      有什么方法可以将局部变量作为表达式而不是没有额外运行时成本的语句声明和分配给 JavaScript?

      并非如此,但您可以将eval()comma operator 一起使用。我知道,我知道,eval() 是邪恶的,但它是在表达式 (AFAIK) 中声明 local 变量的唯一方法,尽管我不推荐它,因为引擎不会优化 @987654326 @ 调用。

      function foo(x) {
        return (eval("var y"), y = x * x, y);
      }
      

      编辑:正如Bergi 指出的那样,使用let 会使变量局部于使用eval() 执行的代码内部,导致y = x * x 创建一个名为y 的全局变量.应该改用var

      【讨论】:

      • 嘿,这一个有趣的解决方案,我没有想到。当然,这并不能解决问题,因为额外的函数调用会比在每个 let 上调用 eval 快得多,但你会得到创造力的积分。
      • 实际上,这确实声明了一个全局变量(出于某种我还不太明白的原因),并且它肯定会在严格模式下失败,其中let-declared 变量受制于本地evaled 表达式内的范围。
      • @Bergi 我发现了问题并编辑了我的答案。谢谢。
      • @D.Pardal 哦,当然,创建全局变量的不是let y 全局评估,而是草率模式下的y = … 赋值。感谢更新。但是请注意,即使 var 在严格模式下也不起作用。
      猜你喜欢
      • 2018-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 2011-07-24
      • 2011-02-23
      • 1970-01-01
      相关资源
      最近更新 更多