这是一个相当快的无限递归序列的惯用F#吗?

这是一个相当快的无限递归序列的惯用F#吗?,f#,immutability,seq,F#,Immutability,Seq,在求解时,我开始做一个无穷序列,得到连续的三角形数。我的第一次尝试是: let slowTriangularNumbers = let rec triangularNumbersFrom n = seq { yield seq { 0 .. n } |> Seq.sum yield! triangularNumbersFrom (n + 1) } triangularNumbersFrom 1 let fasterTriangu

在求解时,我开始做一个无穷序列,得到连续的三角形数。我的第一次尝试是:

let slowTriangularNumbers =

  let rec triangularNumbersFrom n = 
    seq { 
      yield seq { 0 .. n } |> Seq.sum
      yield! triangularNumbersFrom (n + 1) 
    }

   triangularNumbersFrom 1
let fasterTriangularNumbers =

  let cache = System.Collections.Generic.Dictionary<int, int>()
  cache.[0] <- 0         

  let rec triangularNumbersFrom n = 
  seq { 
    cache.[n] <- cache.[n - 1] + n                   
    yield cache.[n]
    yield! triangularNumbersFrom (n + 1) 
  }

  triangularNumbersFrom 1
结果证明这是非常缓慢的-每次获取下一项时,它都必须计算导致
n
的所有加法

我的下一次尝试是:

let slowTriangularNumbers =

  let rec triangularNumbersFrom n = 
    seq { 
      yield seq { 0 .. n } |> Seq.sum
      yield! triangularNumbersFrom (n + 1) 
    }

   triangularNumbersFrom 1
let fasterTriangularNumbers =

  let cache = System.Collections.Generic.Dictionary<int, int>()
  cache.[0] <- 0         

  let rec triangularNumbersFrom n = 
  seq { 
    cache.[n] <- cache.[n - 1] + n                   
    yield cache.[n]
    yield! triangularNumbersFrom (n + 1) 
  }

  triangularNumbersFrom 1
让FasterTriangularNumber=
让cache=System.Collections.Generic.Dictionary()

缓存。[0]我认为这更惯用:

Seq.unfold (fun (i, n) -> Some(n, (i+1, n+i))) (2, 1)
您可能更喜欢这种选择:

seq { 2 .. System.Int32.MaxValue }
|> Seq.scan (+) 1

我猜这相当于:let rec loop(n,diff)=seq{yield n yield!loop(n+diff,diff+1)}loop(1,2),这是Tomas Petricek在另一个答案中提供的。请您解释一下“Some”在这里做什么好吗?@NickL
Seq.unfold
迭代地(但缓慢地)调用指定的函数,直到它返回
None
。通过总是返回
Some
,Jon的实现产生了一个无限序列。@NickL:与手工编写序列表达式相比(除了简洁性),主要的优点是保证没有尾部调用问题。您可以轻松地编写泄漏堆栈空间导致堆栈溢出的序列表达式。如果使用
顺序展开
,则不存在该问题。