在 FSI 我输入
> let a = 10;;
val a : int = 10
> let a = a + 1;;
val a : int = 11
看起来我在这里有一个可变变量?我错过了什么吗?
在 FSI 我输入
> let a = 10;;
val a : int = 10
> let a = a + 1;;
val a : int = 11
看起来我在这里有一个可变变量?我错过了什么吗?
It is not a mutable value. But you use the shadowing : in F#, value shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope.
If you want to have a mutable value, there is a syntaxe in F# :
let mutable a = 10
a <- a + 1
正如 Arthur 已经解释的那样,您看到的是阴影,这意味着命名的原始“变量”a
被一个也命名的新“变量”隐藏a
(我在引号中使用变量,因为它们实际上是不可变的值)。
要查看差异,您可以在函数中捕获原始值,然后在隐藏原始值后打印该值:
> let a = 10;; // Define the original 'a' value
val a : int = 10
> let f () = a;; // A function captures the original value
val f : unit -> int
> let a = 42;; // Define a new value hiding the first 'a'
val a : int = 42
> f();; // Prints the original value - it is not mutated!
val it : int = 10
可悲的是,您不能使用完全相同的代码来查看let mutable
行为方式(因为 F# 不允许在闭包中捕获可变引用),但是当您使用引用单元格(即,在堆中存储可变值的简单对象)时,您可以看到突变):
> let a = ref 10;; // Create a mutable reference cell initialized to 10
val a : int ref = {contents = 10;}
> let f () = !a;; // A function reads the current value of the cell
val f : unit -> int
> a := 42;; // Overwrite the value in the cell with 42
val it : unit = ()
> f();; // Prints the new value - it is mutated
val it : int = 42
您可以在 F# 交互中逐行运行代码,但是当您复制整个片段(输入行)并将它们放在普通 F# 代码中时,它会执行完全相同的操作 - 例如,在函数或模块中。只是为了;;
在 F# 交互输入中结束行(我在 F# 交互窗口中键入了代码),但在普通代码中不需要它,因为 F# 使用缩进来查找语句的结束位置。