Can anyone tell me why this Counter struct won't work? It always resets the value to 0 between calls to Incr.
type Counter =
struct
val mutable i: int
member public this.Incr() =
this.i <- this.i + 1
member public this.Count =
this.i
end
let noCounty(s:string): int =
let x = new Counter()
x.Incr()
x.Incr()
x.Count
The semantics of mutable structs is always confusing, because there are situations where the struct is unexpectedly copied when you use it in certain ways - so it is a good idea to avoid mutation inside structs.
You can make this work by marking the x
variable inside noCounty
mutable. Given your current definition of Counter
, the following works as expected:
let noCounty() =
let mutable x = new Counter()
x.Incr()
x.Incr()
x.Count
I agree this is pretty confusing. I think the logic is that if you define the variable as immutable, then the compiler copies the value of the struct into a new variable before making any call that might mutate it. As a result, the compiled code looks more like:
let noCounty () =
let x = new Counter()
(let t1 = x in t1.Incr())
(let t2 = x in t2.Incr())
(let t3 = x in t3.Count)
I would expect the compiler to give me some warning about this - so perhaps the lack of warning in this case should be reported as a compiler bug. (Though the behaviour is probably intended.)