【发布时间】:2010-07-16 13:33:21
【问题描述】:
这个 F# seq 表达式在我看来是尾递归的,但我遇到了堆栈溢出异常(启用了尾调用)。有人知道我错过了什么吗?
let buildSecondLevelExpressions expressions =
let initialState = vector expressions |> randomize
let rec allSeq state = seq {
for partial in state do
if count partial = 1
then yield Seq.head partial
if count partial > 1 || (count partial = 1 && depth (Seq.head partial) <= MAX_DEPTH) then
let allUns = partial
|> pick false 1
|> Seq.collect (fun (el, rr) -> (createExpUnaries el |> Seq.map (fun bn -> add rr bn)))
let allBins = partial // Careful: this case alone produces result recursivley only if |numbers| is even (rightly!).
|> pick false 2
|> Seq.collect (fun (el, rr) -> (createExpBinaries el |> Seq.map (fun bn -> add rr bn)))
yield! allSeq (interleave allBins allUns)
}
allSeq initialState
如果您想知道,尽管它不应该很重要,pick 用于生成序列中的元素组合,interleave 将来自 2 个序列的元素交错。 vector 是 ResizeArray 的构造函数。
【问题讨论】:
-
yield! allSeq ...在 for 循环中。它不是尾递归的。 -
@Yin:
yield!根本不是尾递归的,例如枚举let rec xs() = seq {yield! xs()}也会导致堆栈溢出。 -
yield!is tail-recursive 当它处于尾部调用位置时,但它似乎在 Jon 发布的退化示例中不起作用(我认为是一个错误)。然而,在所有现实的例子中,这应该是可行的。
标签: f# stack-overflow tail-recursion