Warning triggered by f #: value was copied to ensure that the original is not mutated

The first definition below gives a warning in the header when compiling with f # 3.0 and the warning level set to 5. The second definition compiles cleanly. I was wondering if anyone could explain that the compiler is worried that I might accidentally mutate, or how it would split the expression with the let clause to avoid this. Many thanks.

let ticks_with_warning () : int64 = System.DateTime.Now.Ticks let ticks_clean () : int64 = let t = System.DateTime.Now t.Ticks 
+7
source share
1 answer

I can’t explain why the compiler generates this warning in your particular case - I agree with @ildjarn that you can safely ignore it, because the compiler is probably just too careful.

However, I can give an example where a warning can give you a useful hint that something might not go as you expected. If we used mutable struct as follows:

 [<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 structure (and you can also access the mutable ticks field). We can try to write a function that creates a Test value and modifies 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 of t as mutable , so the compiler tries to make sure that the value does not mutate when Inc called. He does not know whether Inc changes the value or not, so the only security is to create a copy - and therefore foo returns the value Test(1L) .

If we mark t as mutable , then the compiler does not need to worry about changing it as a result of the call, and therefore it does not give a warning (and the function returns Test(2L) ):

 let foo () = let mutable t = Test(1L) t.Inc() t 

I'm not quite sure what triggers the warning in your example. Perhaps the compiler thinks (as a result of some intermediate representation) that the ticks operation can change the value on the left ( System.DateTime.Now and t respectively), and it wants to prevent this.

It is strange that if you write your own DateTime structure in F #, you will get a warning in both cases if you do not mark the variable t as mutable (this is what I expect), but the behavior with the DateTime standard is different. So maybe the compiler knows something about the standard type that I am missing ...

+8
source

All Articles