The first definition below produces the warning in the title when compiled with f# 3.0 and the warning level set to 5. The second definition compiles cleanly. I wondered if someone could please explain just what the compiler worries I might accidentally mutate, or how would splitting the expression with a let clause help avoid that. Many thanks.
let ticks_with_warning () : int64 =
System.DateTime.Now.Ticks
let ticks_clean () : int64 =
let t = System.DateTime.Now
t.Ticks
I cannot really explain why the compiler emits this warning in your particular case - I agree with @ildjarn that you can safely ignore it, because the compiler is probably just being overly cautious.
However, I can give you an example where the warning might actually give you a useful hint that something might not go as you would expect. If we had a mutable struct
like this:
[<Struct>]
type Test =
val mutable ticks : int64
member x.Inc() = x.ticks <- x.ticks + 1L
new (init) = { ticks = init }
Now, the Inc
method mutates the struct (and you can also access the mutable field ticks
). We can try writing a function that creates a Test
value and mutates it:
let foo () =
let t = Test(1L)
t.Inc() // Warning: The value has been copied to ensure the original is not mutated
t
We did not mark the local value t
as mutable
, so the compiler tries to make sure the value is not mutated when we call Inc
. It does not know whether Inc
mutates the value or not, so the only safe thing is to create a copy - and thus foo
returns the value Test(1L)
.
If we mark t
as mutable
, then the compiler does not have to worry about mutating it as a result of a call and so it does not give the warning (and the function returns Test(2L)
):
let foo () =
let mutable t = Test(1L)
t.Inc()
t
I'm not really sure what is causing the warning in your example though. Perhaps the compiler thinks (as a result of some intermediate representation) that Ticks
operation could mutate the left-hand-side value (System.DateTime.Now
and t
respectively) and it wants to prevent that.
The odd thing is that if you write your own DateTime
struct in F#, you get a warning in both cases unless you mark the variable t
as mutable
(which is what I'd expect), but the behaviour with standard DateTime
is different. So perhaps the compiler knows something about the standard type that I'm missing...
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