Mutable values are not allowed in closures, but the for .. in
expression is ok. In C# the for loop updates the iterator, but not in F# as it seems. How and why?
F#'s for .. in
is equivalent to C#'s foreach
loop, not C#'s for
loop. And since C# 5, the foreach
loop does not update the iterator; it instead creates a new variable for each iteration through the loop (this has important implications for closures; see Foreach now captures variables! (Access to modified closure) for details. This is also what F# does: if you write
for txt in ["abc"; "def"; "ghi"] do
printfn "%s" txt
then you're actually creating three new string variables when you run that loop, not just one.
To prove to yourself that F# is creating a new variable each time, try the following not-very-functional code:
let actions = new System.Collections.Generic.List<System.Action<unit>>()
for txt in ["abc"; "def"; "ghi"] do
actions.Add(fun () -> printf "%s " txt)
for action in actions do
action.Invoke()
If txt
was the same variable each time through the for .. in
loop, this would print ghi ghi ghi
, just like C# 4 and earlier would have -- because the anonymous function closed over the variable, and after the loop the variable contains ghi
. But if you run the above code, you'll see that it prints abc def ghi
, like C# 5 and later do.
So the answer to your question is that F# allows for .. in
in a closure because it's not actually mutating anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With