bradgonesurfing
bradgonesurfing

Reputation: 32162

Why does FSharp interactive allow mutable let?

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

Answers (2)

Tomas Petricek
Tomas Petricek

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

ArthurCPPCLI
ArthurCPPCLI

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

Related Questions