繁体   English   中英

在F#中不可变

[英]immutable in F#

我知道F#中的变量默认是不可变的。 但是,例如在F#interactive中:

  > let x = 4;;

val x : int = 4

> let x = 5;;

val x : int = 5

> x;;
val it : int = 5
> 

所以,我将4分配给x,然后将5分配给x并且它正在改变。 这是对的吗? 它应该给出一些错误或警告吗? 或者我只是不明白它是如何工作的?

当你写let x = 3 ,你将标识符x绑定到值3 如果在同一范围内第二次执行此操作,则会声明一个隐藏前一个标识符的新标识符,因为它具有相同的名称。

通过破坏性更新运算符<-来改变F#中的值。 对于不可变值,这将失败,即:

> let x = 3;;

val x : int = 3

> x <- 5;;

  x <- 5;;
  ^^^^^^

stdin(2,1): error FS0027: This value is not mutable

要声明一个可变变量,请在let之后添加mutable

let mutable x = 5;;

val mutable x : int = 5

> x <- 6;;
val it : unit = ()
> x;;
val it : int = 6

但你可能会问,两者之间有什么区别? 一个例子就足够了:

let i = 0;
while i < 10 do
    let i = i + 1
    ()

尽管出现了,但这是一个无限循环。 i在循环中声明的是一个隐藏外部的i 外部的一个是不可变的,因此它始终保持其值0并且循环永远不会结束。 写这个的正确方法是使用一个可变变量:

let mutable i = 0;
while i < 10 do
    i <- i + 1
    ()

x没有改变,它只是被下一个声明隐藏了。 例如:

> let x = 4;;
val x : int = 4
> let x = "abc";;
val x : string = "abc"
>

您没有为x分配5,而是定义了一个新变量。

以下示例显示有两个不同的变量。 (它还表明你可以“访问”旧的x,如果它在一个闭包中,由另一个函数使用):

let x = 5;;
let f y = y+x;;
f 10;;
let x = 0;;
f 10;;

产量

>
val x : int = 5

>
val f : int -> int
> val it : int = 15
>
val x : int = 0

> val it : int = 15

如你所见,对f的两次调用都使用第一个变量x 定义let x = 0;; 定义一个新变量x ,但不重新定义f

这是一个最小的例子,用于说明F#中的标识符“阴影”(即隐藏):

let x = 0
do //introduce a new lexical scope
    let x = 1 //"shadow" (i.e. hide) the previous definition of x
    printfn "%i" x //prints 1
//return to outer lexical scope
printfn "%i" x //prints 0, proving that our outer definition of x was not mutated by our inner definition of x

您的示例实际上有点复杂,因为您正在使用F#Interactive(FSI)。 FSI在您的示例中动态发出类似于以下内容的代码:

module FSI_0001 =
    let x = 4;;

open FSI_0001 //x = 4 is now available in the top level scope
module FSI_0002 =
    let x = 5;;

open FSI_0002 //x = 5 is now available in the top level scope, hiding x = 4
module FSI_0003 =
    let it = x;;

open FSI_0003
//... subsequent interactions

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM