编译器是否可以优化递归调用?

时间:2019-03-21 04:54:02

标签: go tail-recursion

假设我具有此功能:

func abc(i int) (e error) {
    defer func() {
        if r := recover(); r != nil {
            abc(i * 2)
        }
    }()

    if someCondition(i) {
      return fmt.Errorf("Some Err");
    }

    return action() // returns err (nil in case of success) or panics
}

这将被视为尾递归调用吗?可以像尾部递归调用一样优化编译器吗?

我知道以这种方式抑制恐慌不是一个好的决定,但是假设存在正确的condition()函数,该函数是安全的并且可以正确确定何时退出。

2 个答案:

答案 0 :(得分:5)

两句话在​​这里说:

  • recover()将把值传递给panic。在您的情况下,除非someCondition恐慌,否则recover将始终返回nil。所以我不确定您要做什么。
  • Go不会进行尾部调用优化,go团队更喜欢有意义的堆栈跟踪。有关于它的讨论,但尚未达成共识。

如果您要执行的操作是将i * 2乘以条件为真,则只需执行以下操作:

// using recursion
func abc(i int) error {
    if err := someCondition(i); err != nil {
      return abc(i * 2);
    }
    return nil
}

// using loop
func abc(i int) error {
    for someCondition(i) != nil {
        i *= 2
    }
    return nil
}

答案 1 :(得分:2)

  

这将被视为尾递归调用吗?

不。

  

编译器可以优化它,因为可以优化尾部调用吗?

否。

不要那样做。这样的聪明是不行的。