f# essential - part 9 - no need to use ref record type in class
As I discussed it in post f# essential - part 5 - mutable, ref, ref record is used for closure. And mutable is similar concept of variable in c#. So that you can not use mutable defined outside of a function. So the following it is wrong
let build_t() = let mutable x = 0 let t() = x <- 1 + x printfn "you call me %i time(s)" x t let t = build_t() t()
You have to convert it ref record type like the following.
let build_t() = let x = ref 0 let t() = x := 1 + !x printfn "you call me %i time(s)" !x t
If we define method in a class using F#, and we want to update the member field in a method, should we also use mutable or ref record. It turns out, both of them are supported.
type Foo() = let mutable callT1Count = 0 let callT2Count = ref 0 member x.t1() = callT1Count <- callT1Count + 1 printfn "you call t1 %i time(s)" callT1Count member x.t2() = callT2Count := !callT2Count + 1 printfn "you call t2 %i time(s)" !callT2Count let f = new Foo() f.t1() f.t2()
I used reflector to decompile it to c# code as follow to know that that is implemented in .net
[Serializable, CompilationMapping(SourceConstructFlags.ObjectType)] public class Foo { // Fields internal int callT1Count = 0; internal FSharpRef<int> callT2Count = Operators.Ref<int>(0); // Methods public void t1() { this.callT1Count++; FSharpFunc<int, Unit> func = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<int, Unit>>(new PrintfFormat<FSharpFunc<int, Unit>, TextWriter, Unit, Unit, int>("you call t1 %i time(s)")); int num = this.callT1Count; func.Invoke(num); } public void t2() { Operators.op_ColonEquals<int>(this.callT2Count, Operators.op_Dereference<int>(this.callT2Count) + 1); FSharpFunc<int, Unit> func = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<int, Unit>>(new PrintfFormat<FSharpFunc<int, Unit>, TextWriter, Unit, Unit, int>("you call t2 %i time(s)")); int num = Operators.op_Dereference<int>(this.callT2Count); func.Invoke(num); } }
Why mutable is not supported in closure? I think the reason is that when you create an instance of Class, the variable (mutable) is already closed in an instance. Of course, ref type is still supported, but but I think it is double closed. We only need to use variable(mutable) in class.