簡體   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