Cover by Chris Smith

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

O'Reilly logo

Sequences

The most common use of lazy evaluation is through the sequence or seq type in F#, which represents an ordered sequence of items, much like a List. The following snippet defines a sequence of five elements and iterates through them using the Seq.iter function. (Just like the List module, there is a whole slew of available functions to use on sequences.)

> let seqOfNumbers = seq { 1 .. 5 };;

val seqOfNumbers : seq<int>

> seqOfNumbers |> Seq.iter (printfn "%d");;
1
2
3
4
5
val it : unit = ()

Note

The difference between a seq and a list is that only one element of a sequence exists in memory at any given time. seq is just an alias for the .NET interface System.Collections.Generic.IEnumerable<'a>.

So why have this limitation? Why have two types when you can just use a list? Because having all list contents in memory means you are resource-constrained. You can define an infinite sequence quite easily, but an infinite list would run out of memory. Also, with lists, you must know the value of each element ahead of time, whereas sequences can unfold dynamically (in so-called pull fashion).

Example 3-11 defines a sequence of all possible 32-bit integers represented as strings. It then tries to create an equivalent list, but fails due to memory.

Example 3-11. A sequence of all integers

> // Sequence of all integers
let allIntsSeq = seq { for i = 0 to System.Int32.MaxValue -> i };; val allIntsSeq : seq<int> > allIntsSeq;; val it : seq<int> = seq [0; 1; 2; 3; ...] > // List of all integers ...

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required