# Why can't methods be defined inside a \`let\` block?

**URL:** https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818
**Category:** New to Julia
**Tags:** question, scope
**Created:** [August 12, 2020, 5:31pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818 "2020-08-12T17:31:58Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![nben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nben/32/11164_2.png) [@nben](https://discourse.julialang.org/u/nben)
#### Post date: [August 12, 2020, 5:31pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818/1 "2020-08-12T17:31:58Z")

</div>

When one runs the following code, my expectation is that three methods would get defined.

```julia
# Default equal function:
preferred_equal_fn(x) = (===)

# Numbers use isequal
let x = isequal
    preferred_equal_fn(::Type{T}) where {T <: Number} = x
end

# So do strings.
begin
    local x = isequal
    preferred_equal_fn(::Type{T}) where {T <: AbstractString} = x
end

```

However, the `let` block seems to prevent the definition:

```julia
methods(preferred_equal_fn)
# [Out] := #2 methods for generic function preferred_equal_fn:
# preferred_equal_fn(::Type{T}) where T<:AbstractString in Main at In[1]:12: 
# preferred_equal_fn(x) in Main at In[1]:2

```

What’s going on here? Is this documented anywhere?

---

<div class="post-metadata">

### Author: ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)
#### Post date: [August 12, 2020, 5:39pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818/2 "2020-08-12T17:39:13Z")

</div>

`let` creates a “hard” scope, see [Scope of Variables · The Julia Language](https://docs.julialang.org/en/v1/manual/variables-and-scoping/).

To define a method in a `let` block, you need to manually use the `global` keyword:

```julia
# Numbers use isequal
let x = isequal
    global preferred_equal_fn(::Type{T}) where {T <: Number} = x
end

```

---

<div class="post-metadata">

### Author: ![nben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nben/32/11164_2.png) [@nben](https://discourse.julialang.org/u/nben)
#### Post date: [August 12, 2020, 6:03pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818/3 "2020-08-12T18:03:05Z")

</div>

Thanks; that the `global` keyword fixes this seems intuitive. I seem to be a bit confused about the specific terminology, though. The documentation says that that `begin` blocks do not introduce a new scope, but it seems that they do respect `local` definitions, which I had taken to indicate a scoping layer.

```julia
x = 20
begin
    local x = 10
    println(x)
end
println(x)
# [Out] := 10
# [Out] := 20

```

Am I correct in thinking that soft and hard scopes actually have an effect on whether keywords like `local` are implicitly prepended to variable assignments inside them, while `begin` blocks form a kind of very-soft scope that doesn’t prepend anything?

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [August 12, 2020, 7:00pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818/4 "2020-08-12T19:00:56Z")

</div>

```julia
julia> x = 20
20

julia> begin
        x=20
        println(x)
        end
20

julia> x
20

julia> let x = 10
       print(x)
       end
10
julia> x
20

```

I hope this helps you to clear the view, basically, your `begin` + `local` is the same as a let block with local variables, and if you don’t have `local`, then you can directly change `x` inside the `begin` I think

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [August 12, 2020, 7:25pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818/5 "2020-08-12T19:25:27Z")

</div>

I think this is more to do with the fact that `local` in global scope acts a little funny. E.g., you can do:

```julia
julia> x = 20
20

julia> local x = 10
10

julia> x
20

julia> (begin
       local x = 10
       end; println(x)); println(x)
10
20

```

It’s not the `begin` block that’s introducing the scope, it’s the evaluation of the complete expression itself.

Edit: This is [issue #10472](https://github.com/JuliaLang/julia/issues/10472).

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [August 12, 2020, 7:27pm UTC](https://discourse.julialang.org/t/why-cant-methods-be-defined-inside-a-let-block/44818/6 "2020-08-12T19:27:14Z")

</div>

Interesting…

```julia
julia> local x = 10
10

julia> x
ERROR: UndefVarError: x not defined

```

So, `begin` + `local` only allow one to reference that local name.  
Cf

```julia
julia> let
           local x = 5
           begin
               local x = 10
               println(x)
           end
           println(x)
       end
10
10

```
