9

我们知道在 F# 中,seq 是惰性求值的。我的问题是,如果我有一个值数量有限的 seq,如何将其转换为包含其所有评估值的数据类型?

> seq { for i in 1 .. 10 do yield i * i };;
val it : seq<int> = seq [1; 4; 9; 16; ...]

非常感谢。

4

2 回答 2

23

@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.toListSeq.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

于 2016-02-03T07:22:53.393 回答
9

使用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|]
于 2016-02-03T05:40:19.307 回答