let rect = new Rectangle(x, y, sprite.Width, sprite.Height)
rect.X <- 888
The second line fails in F#, but in C# the assignment works. I am not sure why.
let rect = new Rectangle(x, y, sprite.Width, sprite.Height)
rect.X <- 888
The second line fails in F#, but in C# the assignment works. I am not sure why.
Rectangle
is a struct rather than a class. You can have that line work as you'd expect if you mark the value with mutable
:
let mutable rect = new Rectangle(10, 21, 10, 21)
rect.X <- 888
This is actually quite interesting, as F# makes the value-type semantics of structs more visible compared to what C# does.
rect.X <- 888
does not really mutate the field, rather it updates rect
with a new value of the struct with the X field modified. So you can imagine it does an equivalent of rect <- { rect with X = 888 }
. At that point it's quite clear why the compiler wants to see mutable
there.
I wonder why F# designers didn't prohibit assignment syntax for structs and go with something similar to the record syntax. Probably they didn't want to make it too different compared to C#.
As the compiler is probably saying,
A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'
In F#, let
creates an immutable variable (i.e. a value). The compiler enforces this by not letting you mutate it. You must write let mutable
to get an equivalent variable declaration to what you had in C#.
Note that if Rectangle was a reference type, F# wouldn't complain, because you'd be modifying what is referenced by the value, not the value itself. In the case of a value type (like Mono's Rectangle), the identifier bound to the value is the value itself, so you cannot mutate it.