在第三章中,我们谈到如何使用关键字let绑定标识符到值,并指出在那些情况下可以重新定义和恢复之前的值,但是不能修改。如果你想定义一个标识符,其值可以随时间而改变(亦即随程序运行而改变),你可以使用mutable关键字,用于更新这些标识符的是一个特殊的操作符,左ASCII箭头(或只是左箭头),由一个小于号和破折号(-)组成。使用左箭头的更新操作具有unit类型,所以你可以链接多个操作。下一个例子演示如何定义一个字符串类型的mutable标识符,然后改变它的值。
#light
let mutable phrase = "How can I be sure, " print_endline phrase phrase <- "In a world that's constantly changing" print_endline phrase 执行结果: How can I be sure, In a world that's constantly changing乍一看,这与重新定义一个标识符并没有明显的不同,但它有一对不同的关键字。当你使用左箭头更新一个mutable标识符时,你可以改变它的值,但不能改变它的类型,当你重新定义一个标识符时,你两者都可改变。如果你尝试更改mutable标识符的类型将产生一个编译错误,下面演示了这种情况。
#light
let mutable number = "one" phrase <- 1试图编译这段代码时,你会得到以下错误消息: Prog.fs(9,10): error: FS0001: This expression has type int but is here used with type string其它主要的区别是,这些变化一直可见。而当你重新定义一个标识符,改变的值仅在新标识符范围内可见,如果超出范围,标识符将恢复旧值。这些情况不同于mutable标识符,任何改变都是永久的,没有范围。下面的例子演示了这一点。
#light
let redefineX() = let x = "One" printfn "Redefining:\r\nx = %s" x if true then let x = "Two" printfn "x = %s" x else () printfn "x = %s" x let mutableX() = let mutable x = "One" printfn "Mutating:\r\nx = %s" x if true then x <- "Two" printfn "x = %s" x else () printfn "x = %s" xredefineX()
mutableX() 执行结果 Redefining: x = One x = Two x = One Mutating: x = One x = Two x = Twomutable定义的标识符有些限制,它们不能在子函数中使用。你可以在下面的例子中看到。
#light
let mutableY() = let mutable y = "One" printfn "Mutating:\r\nx = %s" y let f() = y <- "Two" printfn "x = %s" y f() printfn "x = %s" y 编译和执行这个例子时的结果如下: Prog.fs(35,16): error: The mutable variable 'y' has escaped its scope. Mutable variables may not be used within an inner subroutine. You may need to use a heapallocated mutable reference cell instead, see 'ref' and '!'.正如错误消息提示,你需要ref类型,一种特殊的记录类型,提供在几个函数之间共享的mutable变量,我们将在下一节讨论ref类型的可变记录。