我知道,在F#变量默认情况下不可变的。 但是,例如在F#互动:
> let x = 4;;
val x : int = 4
> let x = 5;;
val x : int = 5
> x;;
val it : int = 5
>
所以,我给你4 x,那么5 x和它的变化。 这是对的吗? 应该给一些错误或警告? 或者,我只是不明白它是如何工作的?
我知道,在F#变量默认情况下不可变的。 但是,例如在F#互动:
> 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
要声明一个可变变量,加上mutable
后let
:
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"
>
你并没有使用5到x
,你要定义一个新的变量。
下面的例子表明,有两个不同的变量。 (这也表明,你可以“访问”老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#互动(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