Error FS0037 sometimes, very confusing

If I write the following F # code, the compiler throws an error.

let a = 123 let a = 123 

An error has occurred:

error FS0037: Duplicate definition of 'a'

If I write the same code in a function like this:

 let fctn = let a =123 let a =123 a 

It does not cause errors.

I do not understand the difference. Can someone explain?

Edit: The first code I write is at the module level.

+1
source share
3 answers

I agree that this is confusing. The problem is that let behaves differently when used as a local variable (inside a function) and when it is used as a global definition (inside a module).

Global definitions (in a module) are compiled as static members of a static class, so the name can only be used once. This means using top level:

 let a = 10 let a = 11 

... is a mistake because F # would have to create two static members with the same name.

Local definitions (inside a function or other nested scope) are compiled into IL, and the variable name essentially disappears (IL uses the stack instead). In this case, F # allows for variable shading, and you can hide the existing name variable. It can be inside a function or even a do block:

 do let a = 10 let a = 11 () 

This is a bit confusing because the variable shading only works inside local areas, but not at the top level. It makes sense when you know how things are compiled, though ..

+2
source

by area and shading

as mentioned by CaringDev (but not explained), you will probably see that shading occurs when you make the area more obvious (using the let ... in ... #light can be shortened a bit), but you can still use he even without #light off )

Try the following:

 > let a = 233 in let a = 555 in a;; val it : int = 555 

as you can see, the expression expresses the shadow value of a - but the original is not lost:

 > let a = 233 in (let a = 555 in a), a;; val it : int * int = (555, 233) 

it's just not in the realm of internal let ... in ...

btw: you can rewrite your example to:

 let fctn = let a = 123 in (let a =123 in a) 

(I added parentheses to make this more obvious)


the other at the module level really defines the value for the scope of the module and is not really an expression, but a definition

+4
source

The first defines two public values ​​with the same name.

The second hides (shadows) meaning.

With the first, you will be an externally visible change in state ( a behaves as mutable), while with the second you cannot (you have two a in different areas).

If you write your statements in the syntax #light off ML, this immediately becomes apparent.

+2
source

Source: https://habr.com/ru/post/1246718/


All Articles