F#: how to evaluate a "seq" to get all its values eagerly?
Asked Answered
A

2

9

We know that in F#, seq is lazy evaluated. My question is, if I have a seq with limited number of values, how to convert it into some data type that contains all its value evaluated?

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

Thanks a lot.

Arbitress answered 3/2, 2016 at 5:37 Comment(0)
E
24

The answer from @Carsten is correct: you can use Seq.toArray or Seq.toList if you wish to convert lazily evaluated sequences to lists or arrays. Don't use these function to force evaluation, though.

The most common reason people tend to ask about this is because they have a projection that involves side effects, and they want to force evaluation. Take this example, where one wishes to print the values to the console:

let lazySeq = seq { for i in 1 .. 10 do yield i * i }
let nothingHappens = lazySeq |> Seq.map (printfn "%i")

The problem is that when you evaluate these two expressions, nothing happens:

> 

val lazySeq : seq<int>
val nothingHappens : seq<unit>

Because nothingHappens is a lazily evaluated sequence, no side-effects occur from the map.

People often resort to Seq.toList or Seq.toArray in order to force evaluation:

> 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]

While this works, it's not particularly idiomatic; it produces a weird return type: unit list.

A more idiomatic solution is to use Seq.iter:

> lazySeq |> Seq.iter (printfn "%i");;
1
4
9
16
25
36
49
64
81
100
val it : unit = ()

As you can see, this forces evaluation, but has the more sane return type unit.

Edomite answered 3/2, 2016 at 7:22 Comment(3)
In my situation the sequence is being constructed from resources which need to disposed after construction. I don't see any other way around this other than calling toList then toSeq, then disposing the resource and returning the result sequence. Evaluation needs to be forced in this instance even though there are no side effects.Bulgaria
@Bulgaria Your example is helpful. Thank you! However, technically there are side effects in your example. The side effects are taking place in the disposable resources.Actuate
This finally solved my own similar problem... and of course it's Ploeh who had the helpful answer and clear explanation. Thanks for everything you do.Pharynx
W
9

use Seq.toArray (for an array) or Seq.toList (for an list) ;)

there are plenty more - just choose ;)


example:

> 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|]
Wrung answered 3/2, 2016 at 5:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.