'mutable' in type definition

Why types are disabled, for example

type t = A of int | B of string * mutable int 

if such types are allowed:

 type t = A of int | B of string * int ref 
+4
source share
2 answers

The question is, how would you change the meaning of the variable element of the discriminatory case of association? For ref types, this is pretty simple, because ref is a reference cell (actually a record) that contains a mutable value:

 match tval with | B(str, refNum) -> refNum := 4 

We extract the reference cell and assign it to the new character (or new variable) refNum . Then we change the value inside the ref cell, which also changes tval , because the two cell references (from the discriminated case of union and from the variable refNum ) are smoothed.

On the other hand, when you write let mutable n = 0 , you create a variable that can be directly mutated, but there is no cell containing a mutable value - the variable n directly changed. This shows the difference:

 let mutable a = 10 let mutable b = a b <- 5 // a = 10, b = 5 let a = ref 10 let b = a b := 5 // a = 5, b = 5 (because of aliasing!) 

So, to answer your question - there is no way to directly refer to the value stored inside the case of discriminated union. You can only extract it using pattern matching, but this copies the value to the new variable. This means that you cannot change the mutable value.

EDIT To demonstrate the limitations of mutable values ​​in F #, here is another example - you cannot commit mutable values ​​inside a closure:

 let foo() = let mutable n = 0 (fun () -> n <- n + 1; n) // error FS0407 

I think the reason is the same as in the case of discriminated unions (although in this case it is not so obvious). The compiler must copy the variable - it is stored as a local variable and as a field in the generated closure. And when copying, you want to change the same variable from multiple links, so anti-aliasing semantics are the only reasonable thing ...

+12
source

Ref is a type ( int ref = ref<int> ). Mutable is not a type; it is a keyword that allows you to update a value.

Example:

 let (bla:ref<int>) = ref 0 //yup let (bla:mutable<int>) = 3 //no! 
+5
source

Source: https://habr.com/ru/post/1300599/


All Articles