Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 不能在序列表达式内使用try/with块。如何避开它?_.net_F# - Fatal编程技术网

.net 不能在序列表达式内使用try/with块。如何避开它?

.net 不能在序列表达式内使用try/with块。如何避开它?,.net,f#,.net,F#,考虑一下 Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. 我选择在F#中创建一个五边形数字序列: 到目前为止还不错。对于大多数情况,我只想计算几个小的整数五边形数。但有时我可能希望得到所有的Int32五边形数字。我在想,继续计算它们是可能的,直到我最终得到一个OverflowException(我使用的是checked算术)。问题是F#对我的想法不太满意,大喊大叫 'try/with' cannot be used

考虑一下

Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2.
我选择在F#中创建一个五边形数字序列:

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

'try/with' cannot be used inside sequence expressions
让这位年轻女士满意的最好办法是什么

假设我想创建一个
int32_pentagonalSeq
,它:

  • 使用
    pentagonalSeq
  • 在试图预测下一项是否可能引发溢出时,不会产生任何额外的计算

  • 谢谢

    你能做点像这样的事情吗

    let pentagonal n = 
       try
          Some(n*(3*n-1)/2)
       with
         | ex -> None
    
    let x = { 1.. Int32.MaxValue } |> Seq.map pentagonal
    

    您可以使用算术来代替序列理解与生成器函数一起使用,如下面的代码段所示:

    open Checked
    let generator n = 
        try
            Some ((n*(3*n-1)/2), n+1)
        with 
           | :? System.OverflowException -> None
    
    let pentagonalSeq = Seq.unfold generator 1
    
    现在,您可以在FSI中看到最后一个五角整数是什么,可以使用此公式计算,而不会出现溢出:

    显然这不是最大的五边形Int32,顺便说一下,是2147438935。但是,要计算1073731660和2147438935之间的五边形数,您需要在
    int
    numbers字段之外进行操作。从某种意义上说,这使得实现初始目标更加容易,因为它不需要检查算术和
    尝试使用
    机器:

    let pentagonalSeq = Seq.unfold
                            (fun n -> let pentagonal = n*(3L*n-1L)/2L in
                                      if pentagonal > (int64 System.Int32.MaxValue) then
                                          None // Sequence is over
                                      else
                                          Some((int pentagonal), n+1L)) // Member and next state
                             1L  // Initial state
    
    再次检查FSI,我们可以看到现在它是一个真正的
    int
    五边形数字序列,事实上:

    pentagonalSeq |> Seq.last;;
    val it : int = 2147438935
    

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

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

    Gene,虽然你给出了一个非常有趣的答案,但它不仅在第1点上失败了,“利用了pentagonalSeq”,因为它在第2点上失败了:“不会产生任何额外的计算,试图预测下一个项目是否可能引发溢出。”@Ownedelysium:真的吗?(1) 我不使用
    pentagonalSeq
    定义是有充分理由的-根据定义,它只允许得到少于一半的
    Int32
    五角数,因此不能作为完整序列的基础;(2)涉及溢出并不是一个完全正确的方法(参见(1)了解结果),因此我根本不使用它们来实现第2点。建议的惯用方法产生完整的
    Int32
    五边形序列,在我看来确实不是“双重失败”。托马斯的回答中引入的非常酷的
    takeWhileNonException
    无法弥补
    pentagonalSeq
    中的缺陷,它会过早溢出。可以通过将mapper函数更改为
    fun n->让nL=int64 n in int(nL*(3L*nL-1L)/2L)
    来修复它。我承认这个问题有点不适定。我并不特别关心五边形溢出,我关心的是正确处理序列,而不是我自己的抛出异常。放松
    pentagonalSeq |> Seq.last;;
    val it : int = 2147438935
    
    let takeWhileNonException (input:seq<_>) = seq { 
      use ps = input.GetEnumerator()
      while (try ps.MoveNext() with _ -> false) do 
        yield ps.Current }
    
    pentagonalSeq
    |> takeWhileNonException
    |> Seq.last