I'm following the F# book Get Programming with F# and got to the part about shadowing. The simplest example they provide doesn't seem to be possible, so I'm wondering if either this syntax was removed or changed for F# 6 shadowing? I haven't been able to find anything stating that or how to do what the book offers as shadowing a record.
type Address =
{ Street: string
Town: string
City: string }
let home = { Street = "123 Main Street"; Town = "The Town"; City = "The City" }
let home = { home with City = "Second City" }
let home = { home with City = "Third City" }
When trying to build get an error stating: Duplicate definition of value 'home'
Edit
So after searching for answers without success as to why this doesn't work I tried putting the above into a function like so:
let testFunction =
let home = { Street = "123 Main Street"; Town = "The Town"; City = "The City" }
let home = { home with City = "Second City" }
let home = { home with City = "Third City" }
0
and it worked just fine. So my question now is why does shadowing work within a function but not outside? Is there a conflict with scoping on a module level that doesn't happen within a function's scope?
To add some more detail to the existing answers, there are four different cases.
Local definitions. If you are inside a function body, you can use shadowing and this is quite useful when doing a computation in multiple steps:
let adjust index =
let index = max 0 index
let index = min 100 index
index
Local definitions inside class. You are similarly allowed to shadow local definitions inside a class:
type A() =
let foo = 1
let foo = 2
member x.Foo = foo
Top-level in a script file. If you are at the top level in a script file (something.fsx
) then you are allowed shadowing. The idea with script files is that they would be run manually, so it is useful to have multiple different versions - you just run the one you want by hand:
let test = calculation1 ()
let test = caluclation2 ()
Top-level in a module (source file). The only case where shadowing does not work is when you are in a module (or .fs
file which becomes a module implicitly). In a module, definitions are public and they are compiled as static members of a class, so there is also a technical limitation (you cannot have multiple class members of the same name).
module Constants =
let answer = 1
let answer = 42 // error FS0037: Duplicate definition of value