不能将 try / 与序列表达式内的块一起使用。如何绕过它?

dev*_*ium 5 .net f#

考虑一下

Pentagonal numbers are generated by the formula, Pn=n(3n?1)/2.
Run Code Online (Sandbox Code Playgroud)

我选择在 F# 中创建一个五边形数字序列:

let pentagonalSeq = { 1..Int32.MaxValue } |> Seq.map (fun n -> n*(3*n-1)/2)
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好。大多数情况下,我只想计算几个小的整数五边形数。但有时我可能希望得到所有的Int32五边形数字。我在想有可能继续计算它们,直到我最终得到一个OverflowException(我使用的是检查算术)。问题是 F# 对我的想法并不特别满意,大喊大叫

'try/with' cannot be used inside sequence expressions
Run Code Online (Sandbox Code Playgroud)

让这位年轻女士满意的最佳方法是什么?

假设我想创建一个int32_pentagonalSeq

  1. 利用 pentagonalSeq
  2. 不会导致任何额外的计算试图预测下一个项目是否可能导致溢出。

谢谢

Tom*_*cek 4

我认为吉恩的答案可能是正确的选择!但是,如果您想使用序列表达式来迭代已有序列的元素,您可以编写如下内容:

let takeWhileNonException (input:seq<_>) = seq { 
  use ps = input.GetEnumerator()
  while (try ps.MoveNext() with _ -> false) do 
    yield ps.Current }
Run Code Online (Sandbox Code Playgroud)

遗憾的是,您不能只用 .. 包装for循环或yield!语句trywith因为(正如您所说),序列表达式不支持异常处理程序。但是,您可以使用底层迭代器并将调用MoveNext包装在异常处理程序中(因为这是一个普通表达式),并false在操作第一次失败时返回。

因此,要获取序列的最后一个数字,您现在可以编写:

pentagonalSeq
|> takeWhileNonException
|> Seq.last
Run Code Online (Sandbox Code Playgroud)