代码之家  ›  专栏  ›  技术社区  ›  Zazaeil

这个特定的递归可以用尾部优化的方式重写吗?

  •  3
  • Zazaeil  · 技术社区  · 6 年前
    phi n 0 = 1
    phi n l = 1 + 1 / phi n (l - 1)
    

    显然,上次评估的操作 不是 递归调用,因此给定的实现确实抛出了足够大的 l

    那么,重写递归的方法(如果有的话)是什么,以便1)它保持递归,2)变得尾部优化?我想 phi n l result 将起作用,但无法相应地重新定义。。。是否有可靠的方法/技术来解决此类问题?

    1 回复  |  直到 6 年前
        1
  •  6
  •   leftaroundabout    6 年前

    所以你有这个计算树:

                   +                 l
                  ╱ ╲
                 1   ÷
                    ╱ ╲
                   1   +             l-1
                      ╱ ╲
                     1   ÷
                        ╱ ╲
                       1  ...
                            ╲
                             +       1
                            ╱ ╲
                           1   ÷
                              ╱ ╲
                             1   1   0
    

    因为这是一个线性形状,所以确实可以使其尾部递归。为此,您需要从底部开始,并将已计算的正确结果保留在累加器变量中。

    phi _ l = go 0 1  -- n isn't actually used
     where go l' acc
            | l' < l     = go (l'+1) $! 1 + 1/acc
            | otherwise  = acc
    

    未测试,此处可能存在off-by-1错误。