Reputation: 32162
In FSI I type
> let a = 10;;
val a : int = 10
> let a = a + 1;;
val a : int = 11
Looks like I have a mutable variable here? Am I missing something?
Upvotes: 0
Views: 259
Reputation: 243041
As already explained by Arthur, what you see is shadowing which means that the original "variable" named a
is hidden by a new "variable" also named a
(I use variable in quotes, because they are actually immutable values).
To see the difference, you can capture the original value in a function and then print the value after hiding the original value:
> 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
Sadly, you cannot use exactly the same code to see how let mutable
behaves (because F# does not allow capturing mutable references in closures), but you can see mutation when you use reference cells (that is, a simple object that stores mutable value in the heap):
> 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
You can run the code line-by-line in F# interactive, but it will do exactly the same thing when you copy the entire snippet (the input lines) and place them in normal F# code - e.g. inside a function or a module. The ;;
is just to end the line in the F# interactive input (I typed the code in the F# Interactive window), but it is not needed in normal code, because F# uses indentation to find out where a statement ends.
Upvotes: 5
Reputation: 1082
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
Upvotes: 5