在FSI中输入
> let a = 10;;
val a : int = 10
> let a = a + 1;;
val a : int = 11
看起来我在这里有一个可变变量?我错过了什么吗?
答案 0 :(得分:5)
这不是一个可变的值。但是你使用阴影:在F#中,当在某个范围内声明的变量(决策块,方法或内部类)与在外部范围内声明的变量具有相同的名称时,会发生值阴影。
如果你想拥有一个可变值,F#中有一个语法:
let mutable a = 10
a <- a + 1
答案 1 :(得分:5)
正如Arthur已经解释的那样,你看到的是 shadowing ,这意味着名为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#interactive中逐行运行代码,但是当您复制整个代码段(输入行)并将它们放在普通的F#代码中时,它会完全相同 - 例如在函数或模块中。 ;;
只是结束F#交互输入中的行(我在F#Interactive窗口中键入代码),但在普通代码中不需要它,因为F#使用缩进来查找语句结束的位置。