我使用以下列表获得了一些可靠的代码:
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,那么是什么给出了?
答案 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