DEV Community

Cover image for F# For Dummys - Day 16 Collections Sequence
AllenZhu
AllenZhu

Posted on • Updated on

F# For Dummys - Day 16 Collections Sequence

Today we learn Sequence, represents an ordered, read-only series of elements

Why Sequence

  • Sequences are particularly useful when you have a large, ordered collection of data but do not necessarily expect to use all of the elements.
  • Individual sequence elements are computed on-demand, so a sequence can provide better performance than a list in situations in which not all the elements are used

What is computed on-demand
like buying a burger in KFC, the staff prepared 1000 burgers in the early morning, so you got your burger immediately, all the burgers are made before customer order, this is called eager evaluation

then you ordered a fried chicken, the staff replies: sorry, you have to wait for a minute, as we need to fry the chicken first, they only do the work when someone ordered, this is called lazy evaluation, also known as On-demand computation

Create Sequence

  • Explicitly specifying elements
let seq1 = seq [1; 2; 3; 4]
printfn "seq: %A" seq1
Enter fullscreen mode Exit fullscreen mode
  • Using range expression
let seq1 = seq { 1 .. 10 } // from 1 to 10
printfn "seq: %A" seq1 // seq: seq [1; 2; 3; 4; ...]
Enter fullscreen mode Exit fullscreen mode

use step in range expression

let seq1 = seq { 1 .. 2 .. 10 } // start from 1, add 2 each time
printfn "seq: %A" seq1 // seq: seq [1; 3; 5; 7; ...]
Enter fullscreen mode Exit fullscreen mode
  • Using for loop
let seq1 = seq { for i in 1 .. 10 -> i }
printfn "seq: %A" seq1
Enter fullscreen mode Exit fullscreen mode
  • ofList Views the given list as a sequence
let inputs = [ 1; 2; 5 ]
let seq1 = inputs |> Seq.ofList
printfn "seq: %A" seq1
Enter fullscreen mode Exit fullscreen mode
  • ofArray
let inputs = [| 1; 2; 5 |]
let seq1 = inputs |> Seq.ofArray
printfn "seq: %A" seq1
Enter fullscreen mode Exit fullscreen mode
  • Seq.initInfinite generate an infinite sequence
let infiniteSeq = Seq.initInfinite (fun i -> i * 2)
printfn "infiniteSeq %A" infiniteSeq
Enter fullscreen mode Exit fullscreen mode

define a start for infinite sequence

let start = 5
let infiniteSeq = Seq.initInfinite (fun i -> i + start)
printfn "infiniteSeq %A" infiniteSeq // infiniteSeq seq [5; 6; 7; 8; ...]
Enter fullscreen mode Exit fullscreen mode

or define a start like this

let infiniteSeq = Seq.initInfinite ((+) 5)
printfn "infiniteSeq %A" infiniteSeq // infiniteSeq seq [5; 6; 7; 8; ...]
Enter fullscreen mode Exit fullscreen mode

Loop Sequence

  • for loop
let numbers = seq { 1 .. 10 }

for number in numbers do
    printfn "Number: %d" number
Enter fullscreen mode Exit fullscreen mode
  • Seq.iter
let numbers = seq { 1 .. 10 }

Seq.iter (fun x -> printfn "Number: %d" x) numbers
Enter fullscreen mode Exit fullscreen mode

Access element

  • Seq.item

syntax: Seq.item index source, thrown ArgumentException when the index is negative or the input sequence does not contain enough elements

let numbers = seq { 1 .. 10 }
let thirdElement = Seq.item 2 numbers  // Indexing is zero-based

printfn "The third element is %d" thirdElement
Enter fullscreen mode Exit fullscreen mode
  • Seq.head && Seq.tail

Seq.head: Returns the first element of the sequence
Seq.tail: Returns a sequence that skips 1 element of the underlying sequence and then yields the remaining elements of the sequence

let numbers = seq { 1 .. 10 }
let firstElement = Seq.head numbers
let restElement = Seq.tail numbers

printfn "The first element is %d" firstElement // The first element is 1
printfn "The rest element is %A" restElement // The rest element is seq [2; 3; 4; 5; ...]
Enter fullscreen mode Exit fullscreen mode

Operate element

  • Seq.updateAt

Return a new sequence with the item at a given index set to the new value
syntax: Seq.updateAt index value source

let newSeq = Seq.updateAt 1 9 seq { 0; 1; 2 }
// let newSeq = Seq.updateAt 1 9 (seq { 0; 1; 2 })
printfn "newSeq: %A" newSeq // newSeq: seq [0; 9; 2]
Enter fullscreen mode Exit fullscreen mode
  • Seq.filter

Returns a new collection containing only the elements of the collection for which the given predicate returns "true". This is a synonym for Seq.where
syntax: Seq.filter predicateFunc sourceSeq

let numbers = seq { 1 .. 10 }
let evenNumbers = Seq.filter (fun x -> x % 2 = 0) numbers

Seq.iter (fun x -> printfn "Even Number: %d" x) evenNumbers
Enter fullscreen mode Exit fullscreen mode
  • Seq.map

Builds a new collection whose elements are the results of applying the given function to each of the elements of the collection
syntax: Seq.filter mappingFunc sourceSeq

let numbers = seq { 1 .. 10 }
let doubleNumbers = Seq.map (fun x -> x * 2) numbers

Seq.iter (fun x -> printfn "doubleNumbers: %d" x) doubleNumbers
Enter fullscreen mode Exit fullscreen mode
  • Seq.fold

Applies a function to each element of the collection
syntax: Seq.fold folderFunc state sourceSeq

type Charge =
     | In of int
     | Out of int
let inputs = [In 1; Out 2; In 3]
let balance = Seq.fold (fun acc charge ->
    match charge with
    | In i -> acc + i
    | Out o -> acc - o) 0 inputs

printfn "balance %A" balance // balance 2
Enter fullscreen mode Exit fullscreen mode

or use pipeline operator to pass state sourceSeq, here is ||> for passing more than one param

type Charge =
     | In of int
     | Out of int
let inputs = [In 1; Out 2; In 3]
let balance = (0, inputs) ||> Seq.fold (fun acc charge ->
    match charge with
    | In i -> acc + i
    | Out o -> acc - o)

printfn "balance %A" balance // balance 2
Enter fullscreen mode Exit fullscreen mode

Top comments (0)