1
votes

I am writing a function that takes a multi-line string through a StringReader and returns each line as an item of a seq

let symbolSeq = seq {

    let mutable line = reader.ReadLine()

    while !line <> null  do
        yield line
        line <- reader.ReadLine()
}

I am getting a

This expression was expected to have type 'a ref but here has type string

on while !--->line<--- <> null do

When I get rid of the ! in front of line I get a

The mutable variable 'line' is used in an invalid way. Mutable variables cannot be captured by closures. Consider eliminating this use of mutation or using a heap-allocated mutable reference cell via 'ref' and '!'.

Why ?

3

3 Answers

3
votes

Because a seq-expression implicitly creates closures, and you can't close over mutable variables in F#.

2
votes

You need to put the line value in a ref cell as mutable values can't be closed over.

let symbolSeq = seq {
let line = ref (reader.ReadLine())
while !line <> null do
    yield !line
    line := reader.ReadLine()
}  
1
votes

An alternative to using a ref cell is to use recursion and yield!:

let symbolSeq =
    let rec iterate (reader : System.IO.StringReader) =
        seq
            {
                match reader.ReadLine() with
                    | null -> ()
                    | x ->
                        yield x
                        yield! iterate reader
            }

    iterate reader