类型定义中的"可变"

ssp*_*ssp 4 f#

为什么禁用类型喜欢

type t = A of int | B of string * mutable int
Run Code Online (Sandbox Code Playgroud)

虽然允许这样的类型:

type t = A of int | B of string * int ref
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 12

问题是,你如何修改受歧视的工会案件的可变元素的价值?对于ref类型,这很容易,因为它ref是一个包含可变值的引用单元格(实际上是一条记录):

match tval with
| B(str, refNum) -> refNum := 4
Run Code Online (Sandbox Code Playgroud)

我们提取参考单元格并将其分配给新符号(或新变量)refNum.然后我们修改ref单元格中的值,它也会修改tval,因为对单元格的两个引用(来自有区别的并集和refNum变量)是别名.

另一方面,当你编写时let mutable n = 0,你正在创建一个可以直接变异的变量,但是没有单元格保存可变值 - 变量n是直接可变的.这显示了不同之处:

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!)
Run Code Online (Sandbox Code Playgroud)

所以,要回答你的问题 - 没有办法直接引用存在于受歧视的联合案例中的值.您只能使用模式匹配来提取它,但会将值复制到新变量.这意味着您无法修改该mutable值.

编辑 为了演示mutableF#中值的限制,这里还有一个例子 - 你无法捕获mutable闭包内的值:

let foo() = 
  let mutable n = 0
  (fun () -> n <- n + 1; n) // error FS0407
Run Code Online (Sandbox Code Playgroud)

我认为其原因与受歧视的工会案件相同(即使在这种情况下并不那么明显).编译器需要复制变量 - 它作为局部变量存储,并作为生成闭包中的字段存储.在复制时,你想要从多个引用修改相同的变量,所以别名语义是唯一合理的事情......


cfe*_*ern 5

Ref是一个类型(int ref = ref<int>).Mutable不是一个类型,它是一个允许您更新值的关键字.

例:

let (bla:ref<int>) = ref 0 //yup
let (bla:mutable<int>) = 3 //no!
Run Code Online (Sandbox Code Playgroud)