【问题标题】:Can JavaScript function call subexpressions be tail calls?JavaScript 函数调用子表达式可以是尾调用吗?
【发布时间】:2021-01-21 22:44:36
【问题描述】:

考虑以下返回语句:

return f() || g();

调用f() 显然不是尾调用,因为如果f() 是假的,函数实际上并没有返回。

g() 部分呢,那是尾声吗?还是我必须像这样重写它:

const temp = f();
if (temp) return temp; else return g();

【问题讨论】:

  • 试试看? “我必须……”
  • 在实践中没关系。无论标准怎么说,只有 Safari 真正支持尾调用优化。
  • JS 编码人员不应该担心实现细节,因为这些细节经常会发生变化;这里的实际问题/问题是什么?
  • @dandavis:消除尾声很重要。
  • @dandavis:尾调用消除允许程序设计在没有尾调用消除的情况下无法工作。这不是实现细节。

标签: javascript tail-recursion tail-call-optimization


【解决方案1】:

是的,但在实践中没有帮助。

根据standardg()处于尾部位置:

逻辑或表达式:逻辑或表达式 ||逻辑与表达式

使用参数调用返回 LogicalANDExpression 的 HasCallInTailPosition。

但是,大多数浏览器 don't support 尾调用消除,Chromium 团队并没有在这方面工作,所以无论你如何编写尾调用,你都不能在实践中依赖尾调用消除。

【讨论】:

    【解决方案2】:

    试试看?

    由于某种原因,在我睡眠不足的状态下我没有想到:D

    function f() {
        return Math.random() > 1 || f();
    }
    
    f()
    

    节点说RangeError: Maximum call stack size exceeded,Firefox 说InternalError: too much recursion

    【讨论】:

    • 那是因为那些引擎根本不支持尾调用消除。
    • @user2357112supportsMonica 即使 ES6 强制要求它?直到
    • 不,Math.random() will never return > 1 - 总是假的,所以f() 被永远调用
    • @RandyCasburn 我故意为这个实验选择了一个始终为假的条件。通过尾调用优化,无限递归不会破坏堆栈,而是永远循环。
    • 啊,当然知道了。 @user2357112supportsMonica - 然后说什么 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 2013-01-21
    相关资源
    最近更新 更多