使用F#序列的不可思议的错误

时间:2014-07-01 05:58:21

标签: .net f# seq

我使用以下列表获得了一些可靠的代码:

      let rec srch (tzs : pqCell list) =
            match tzs with
            | h :: t ->
                 // process h and recurse on t if needed
            | [] -> None

      let zs = this.CellsInDiffOrder()   // a newly constructed list 
               |> List.filter (fun c -> c.nVal = 0 )
      srch zs   

然后我将其转换为使用序列,因为在很多情况下,当递归早期终止时,它会不必要地构建大型列表。

      let rec srch (tzs : pqCell seq) =
            if (Seq.isEmpty tzs) then None
            else
                let h = Seq.head tzs
                let t = Seq.skip 1 tzs
                // process h and recurse on t if needed

      let zs = this.CellsInDiffOrder()   // a newly constructed seq 
               |> Seq.filter (fun c -> c.nVal = 0 )
      srch zs   

这看起来非常出色,可以带来显着的性能提升。但是,由于我无法理解的原因,这有时(但并非总是)失败并显示消息:

The input sequence has an insufficient number of elements.  

以及以下堆栈跟踪:

at Microsoft.FSharp.Collections.SeqModule.Skip@1500.GenerateNext(IEnumerable 1& next) at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase 1.MoveNextImpl()    在Microsoft.FSharp.Collections.SeqModule.Skip@1500.GenerateNext(IEnumerable 1& next) at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase 1.MoveNextImpl()    在Microsoft.FSharp.Collections.SeqModule.Skip@1500.GenerateNext(IEnumerable 1& next) at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase 1.MoveNextImpl()    在Microsoft.FSharp.Collections.SeqModule.Skip@1500.GenerateNext(IEnumerable 1& next) at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase 1.MoveNextImpl()    在Microsoft.FSharp.Collections.SeqModule.Skip@1500.GenerateNext(IEnumerable 1& next) at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase 1.MoveNextImpl()    在Microsoft.FSharp.Collections.SeqModule.Skip@1500.GenerateNext(IEnumerable 1& next) at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase 1.MoveNextImpl()    在C:\ dev \ psq \ psq2.fs中的Microsoft.FSharp.Collections.SeqModule.IsEmpty [T](IEnumerable 1 source) at PsQ2.srch@2506-2.Invoke(IEnumerable 1 zs):第2506行    在PsQ2.Search()在C:\ dev \ psq \ psq2.fs:第2530行

所以跳过1似乎失败了,但是为什么,因为代码只跳过已知非空的序列。我确信没有其他代码可以查看或修改任何有问题的seq,那么是什么给出了?

1 个答案:

答案 0 :(得分:2)

由于我不知道您的代码,让我向您展示一个简单的序列,该序列不通过isEmpty而且在get head上失败。

let i = ref 1
let s = seq { while !i <> 0 do i := 0; yield !i }
//let s = Seq.cache s  //add this line to make things works

assert not (Seq.isEmpty s) //isEmpty works by trying to take one element
let h = Seq.head s