Consider the following F#:-
type TestClass() =
let getValFromMap m k = Map.find k m
let addToMap map k i = map |> Map.add k i
let mutable someMap : Map<string,int> = Map.empty
let getValFromMapPartial key = getValFromMap someMap key
let getValFromMapPartialAndTacit = getValFromMap someMap
member this.AddThenGet() =
someMap <- addToMap someMap "A" 10
let value = getValFromMapPartial "A"
printfn "Value from partial = %i" value // prints out
let value = getValFromMapPartialAndTacit "A" // throws
printfn "Value from partial and tacit = %i" value
[<EntryPoint>]
let main argv =
let test = TestClass()
test.AddThenGet()
0
Functions getValFromMapPartial
and getValFromMapPartialAndTacit
are, to my mind, identical. F# says they have the exact same type: (string -> int)
. And yet they behave very differently, and they are compiled very differently. Decompiling using dotPeek, I see that getValFromMapPartial
is a method, whereas getValFromMapPartialAndTacit
is a field that is initialized in the ctor.
F# does not complain about getValFromMapPartialAndTacit
, even on the highest warning level (both in VS 2012 and 2013). And yet calling this function in my sample above fails, presumably because it has wrapped the initial, empty version of the someMap
, despite its mutability.
Why is there a difference between these two functions? Should there be a warning from F# that the tacit / point-free version might fail?