为什么这个F#表达式堆栈溢出

时间:2014-05-30 12:33:59

标签: f#

let ints = [1..40000]

// create [{1};{2};.....{40000}]
let a1 = ints |> List.map Seq.singleton 

// tail recursively append all the inner list
let a2 = a1 |> List.fold Seq.append Seq.empty

// tail recursively loop through them
let a3 = a2 |> Seq.forall (fun x -> true) // stack overflow...why?

我要问的原因是担心我会有递归附加的代码,我需要确保它不会爆炸....所以我运行这个例子以便确定将要发生的事情

在调试和作为应用程序运行时。

1 个答案:

答案 0 :(得分:3)

首先要注意的是导致SO异常的函数是:

let a2 = a1 |> List.fold Seq.append Seq.empty

但是在评估下一行之前,你不会看到SO,因为序列被懒惰地评估。

因为您正在使用Seq.append,所以添加到序列中的每个新项目都会创建一个包含前一个序列的新序列。您可以直接构造类似的序列:

> seq {
    yield! seq { 
                   yield! seq { 
                                  yield 1
                              }
                   yield 2
               }
    yield 3
}

val it : seq<int> = seq [1; 2; 3]

注意如何到达第一项(1),你必须进入序列的深度3。在你的情况下,深度为40000.序列不是尾递归的,所以序列的每个级别在迭代时最终都是一个堆栈帧。