【问题标题】:Why isn't this tail-recursive?为什么这不是尾递归?
【发布时间】:2012-02-14 14:01:25
【问题描述】:

我正在阅读Real-World Functional Programming 这本书,在阅读本书的示例(清单 10.2,第 265 页)之前,我尝试提出自己的尾递归示例。这本书的例子有效;我的导致堆栈溢出。

我发现如果我使用元组参数或预先计算a + accum,那么我的就可以了。我想明白为什么。

let rnd = new System.Random()
let test2 = List.init 1000000 (fun _ -> rnd.Next(-50, 51))

let rec sum2 list accum =
  match list with
  | [] -> accum
  | a::b -> sum2 b a + accum

let result = sum2 test2 0

printfn "%d" result

【问题讨论】:

    标签: recursion f# tail-recursion


    【解决方案1】:
    sum2 b a + accum
    

    请注意,这被解析为(sum2 b a) + accum,而不是sum2 b (a + accum)

    所以这调用sum2 b a。然后它获取该调用的结果并将accum 添加到其中。所以最后评估的表达式是加法,而不是对sum2 的调用。因此对sum2 的调用不是尾调用。

    【讨论】:

      【解决方案2】:

      也许编译器正在读取

      a::b -> (sum2 b a) + accum
      

      而不是

      a::b -> sum2 b (a + accum)
      

      【讨论】:

      • 啊啊!你和@sepp2k 很到位。是评价顺序。括号修复它。
      • 我通常把所有的东西都用括号括起来,因为我发现它是较小的邪恶。是的,普通的口齿不清!!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多