我们知道在F#中,seq是惰性评估的。我的问题是,如果我有一个数量有限的seq,如何将它转换为包含其所有值的一些数据类型?
> seq { for i in 1 .. 10 do yield i * i };;
val it : seq<int> = seq [1; 4; 9; 16; ...]
非常感谢。
答案 0 :(得分:17)
来自@Carsten的答案是正确的:如果您希望Seq.toArray
或Seq.toList
。但是,不要使用这些功能强制进行评估。
人们倾向于问这个问题的最常见原因是因为他们有一个涉及副作用的预测,他们想要强制进行评估。举个例子,希望将值打印到控制台:
let lazySeq = seq { for i in 1 .. 10 do yield i * i }
let nothingHappens = lazySeq |> Seq.map (printfn "%i")
问题在于,当您评估这两个表达式时,没有任何反复发生:
>
val lazySeq : seq<int>
val nothingHappens : seq<unit>
由于nothingHappens
是一个延迟评估的序列,因此map
不会产生任何副作用。
人们经常诉诸Seq.toList
或Seq.toArray
以强制进行评估:
> nothingHappens |> Seq.toList;;
1
4
9
16
25
36
49
64
81
100
val it : unit list =
[null; null; null; null; null; null; null; null; null; null]
虽然这有效,但并不是特别惯用;它会产生一种奇怪的返回类型:unit list
。
更惯用的解决方案是使用Seq.iter
:
> lazySeq |> Seq.iter (printfn "%i");;
1
4
9
16
25
36
49
64
81
100
val it : unit = ()
正如您所看到的,这会强制进行评估,但具有更合理的返回类型unit
。
答案 1 :(得分:8)
使用Seq.toArray
(对于数组)或Seq.toList
(对于列表);)
还有更多 - 只需选择;)
> seq { for i in 1 .. 10 do yield i * i } |> Seq.toArray;;
val it : int [] = [|1; 4; 9; 16; 25; 36; 49; 64; 81; 100|]