2
let a = 1
let a = 2
let b = a

This code quietly compiles, runs and binds b = 2.

But is this desired behavior? It does allow the coder to reuse an appropriate value name, no objects have been mutated, however in the midst of n lines of code it is all too easy to accidentally use a value name again in the same namespace and in practical terms introduce a bug by mutation. I wonder how this fits with the functional paradigm and if there ought to be a warning of sorts.

rbonallo
  • 970
  • 1
  • 9
  • 21
  • http://stackoverflow.com/questions/11157358/immutable-in-f – Alexan Apr 04 '17 at 20:16
  • 1
    As other pointed out by design values are immutable but bindings are mutable in F#. It's a matter of taste. However, reusing variable names has the drawback of making the code less debuggable as the debugger is designed for C# (which doesn't allow reusing) so one only see the value of the last binding. – Just another metaprogrammer Apr 04 '17 at 20:28

2 Answers2

5

You are not entirely correct, as this is only possible locally.

This behavior is called shadowing. Shadowing is a highly effective way of making the code more readable, and not less comprehensible as you might think if used to imperative languages. It can actually help prevent bugs rather than introduce bugs, by overriding an identifier name, thereby blocking access to the former definition.

Here is an example showing typical usage of shadowing, where types used are Insect option, Insect, and UnclassifiedInsect.

match insect with
| Some insect ->
    match insect with
    | Butterfly butterfly -> printfn "It's a butterfly."
    | UnclassifiedInsect insect -> printfn "New species? %A." insect
| None -> printfn "There was no insect."

PS: F# also has imperative constructs, so there is the possibility to mess up e.g. by mixing shadowing and mutable variables. Simply don't do that. But on the whole, shadowing is a blessing.

Bent Tranberg
  • 3,445
  • 26
  • 35
3

This is an intended behavior for F# and for example OCaml. On the other hand Haskell doesn't allow such thing and throws a compilation error.

mateuszlewko
  • 1,110
  • 8
  • 18