# Either the def of \`local\` is wrong, Or the current julia behavior is unexpected

**URL:** https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903
**Category:** General Usage
**Tags:** question
**Created:** [October 6, 2025, 3:24am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903 "2025-10-06T03:24:18Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 3:24am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/1 "2025-10-06T03:24:18Z")

</div>

The def:

```julia
help?> local
  local introduces a _new_ local variable.

```

Okay. I think this make sense somehow since

```julia
julia> function f(a)
           local a
       end
ERROR: syntax: local variable name "a" conflicts with an argument

```

In the above example, firstly we have an _local_ argument named `a` in the first line.  
Then in the second line we introduce a **new** local name, also named `a`.  
So we will have two _different_ local `a`’s, which will cause ambiguity—thus the ERROR is proper.

Now look at this example

```julia
julia> function c()
           local a
           local a
       end
c (generic function with 1 method)

```

Notice that `c` can be defined!  
I think this doesn’t make sense anyway. It violates the definition of `local`, isn’t it?

Edit: (Also see my #13 post)

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 4:18am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/2 "2025-10-06T04:18:43Z")

</div>

You’re implying that each `local a` statement must create a new local variable. That isn’t true; the 2nd statement is just redundant for that local scope level. The reason why you get an error in `function f(a)` instead of it being redundant is because it strongly implies the user forgot about the argument by mistake. Note that `local` statements often coincide with assignments `local a = 0`, which would make the argument rather useless. That particular danger doesn’t happen with 2 `local a` statements, though that likely mistake could have lesser hazards.

---

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [October 6, 2025, 4:19am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/3 "2025-10-06T04:19:10Z")

</div>

It would be fine for the language to throw an error for the second example, IMO, but there’s no real ambiguity here. It’s just the same local variable being declared twice.

Now, maybe a function argument and a local variable are two distinct things, arguably. On the other hand, I don’t think I’d be upset if the first example didn’t throw an error, either.

Both of these would probably best be flagged by a linter.

Note that you _can_ do

```julia
function f(a)
    @show a
    let # hard sub-scope
        local a = 2
        @show a
    end
end

```

---

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 4:28am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/4 "2025-10-06T04:28:45Z")

</div>

> [@Benny](#):
>
> You’re implying that each `local a` statement must create a new local variable.

It’s not me implying, it’s written as its definition, which is very unclear so that I cannot make further reasoning. You cannot read a math book to the second page with its definitions being wrong.

> [@Benny](#):
>
> Note that `local` statements often coincide with assignments `local a = 0`

No I _strongly_ disagree.  
The standard syntax is just `local x, y, z` without involving any `=`.  
Otherwise it’s extremely easy for users to write `local x = t.a, y = 4`, which mixed up with the `let` syntax. Several days before I spend 3 hours debugging, and finally discover this stupid bug.

---

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [October 6, 2025, 4:32am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/5 "2025-10-06T04:32:33Z")

</div>

> [@WalterMadelim](#):
>
> It’s not me implying, it’s written as its definition

The definition could be construed as a little ambiguous. But, now you know that’s not what that means. If you have any ideas on how to formulate that with less ambiguity, you could open a PR for the docstring.

But seriously: does this cause any problems whatsoever with how you reason about Julia code?

> [@WalterMadelim](#):
>
> Several days before I spend 3 hours debugging, and finally discover this stupid bug.

What exactly is the bug?

---

<div class="post-metadata">

### Author: ![affans](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/affans/32/11911_2.png) [@affans](https://discourse.julialang.org/u/affans)
#### Post date: [October 6, 2025, 4:35am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/6 "2025-10-06T04:35:31Z")

</div>

For consistency, perhaps the first example should **not** throw an error since you can do

```julia-auto
julia> function f(a)
       a = 1
       end
f (generic function with 1 method)

julia> f(3)
1

```

so, within the scope of the function, you can certainly overwrite the function argument. There is not really a big difference in writing `a = 1` and `local a = 1` above, since the scoping is the same. This is also why

```julia-auto
function b()
   local a 
   local a
end

```

is perfectly fine, as nothing prevents you from using the same binding again.

I believe the first error might just be a “we think you are introducing a bug so will error out”.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 4:37am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/7 "2025-10-06T04:37:44Z")

</div>

> [@WalterMadelim](#):
>
> It’s not me implying, it’s written as its definition

Nothing in the docstring contradicts what I said, and the wider Scope of Variables page in the Manual makes it pretty clear that

1. `local` statements introduce a local variable to a particular scope level in contrast with outer local variables of the same name.
2. There is no such thing as 2 local variables of the same name being accessible within the same local scope level. One name means one variable.

> [@WalterMadelim](#):
>
> No I _strongly_ disagree.

Your personal disagreement and difficulties don’t contradict the plain observation that `local` statements do coincide with assignments in practice and in the documentation. As for that particular bug, `local x = t.a, y = 4` doesn’t work because ~~it violates the syntax of an assignment expression.~~ `let` header syntax is specified as a _series_ of assignments or declarations with somewhat different parsing, not a single assignment expression like that.

---

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [October 6, 2025, 4:48am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/8 "2025-10-06T04:48:09Z")

</div>

> [@Benny](#):
>
> As for that particular bug, `local x = t.a, y = 4` doesn’t work because it violates the syntax of an assignment.

The bug being that this is just invalid syntax, but the compiler doesn’t catch it until runtime and then produces a very confusing error? That does seem like something to open an issue with JuliaSyntax over.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 5:06am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/9 "2025-10-06T05:06:21Z")

</div>

I worded that poorly, I wasn’t trying to say it was invalid syntax. I ought to have said the syntax doesn’t mean a sequence of single-variable assignments as WalterMadelim expected from `let` headers. Under normal circumstances, it is a chained assignment, one of the left-hand expressions doing destructuring assignment:

```julia-auto
julia> mutable struct Blah a end

julia> t = Blah(0)
Blah(0)

julia> x = t.a, y = 1:2 # change because integer only has index 1
1:2

julia> x, t, y
(1:2, Blah(1), 2)

```

`let` headers specifying a sequence of assignments or declarations does skew the parsing of otherwise identical text. Here’s an intended destructuring assignment example:

```julia-auto
julia> (x, y) = 1:2; x, y
(1, 2)

julia> x, y = 1:2; x, y # we're allowed to omit parentheses here
(1, 2)

julia> let (x, y) = 1:2
        x, y
       end
(1, 2)

julia> let x, y = 1:2 # parser doesn't play nice anymore
        x, y
       end
ERROR: UndefVarError: `x` not defined in local scope

```

In the last erroring example, we don’t even need the assignments in the `let` header, and it’d work fine if we move those into the `let` body. However, the header necessarily exists to pass values from the outer scope into the `let` body the same way a function call passes keyword arguments into a method body:

```julia-auto
julia> a = 1;

julia> let a = a # left assigns local a, right accesses value of global a
         a+10
       end
11

julia> f(;a) = a+10; f(a = a) # same deal here
11

julia> let
         a = a # can't use 1 name as 2 variables
         a+10
       end
ERROR: UndefVarError: `a` not defined in local scope

```

If it were up to me, I’d further restrict `let` headers to simpler assignment expressions to mimick keyword arguments and explicitly describe it that way, but that’d be a breaking change.

---

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 5:34am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/10 "2025-10-06T05:34:03Z")

</div>

> [@goerz](#):
>
> But seriously: does this cause any problems whatsoever with how you reason about Julia code?

Yes, seriously.

Until here I still don’t know what is the essential effect by writing `local x`. Because of people’s inaccurate wording.

I don’t know if `local x` means:

- introduce a new name `x`, which is required to be a local name in the current scope

or

- We might have owned a name `x` in the current scope already, and now we declare it to be local.

* * *

> [@Benny](#):
>
> and the wider Scope of Variables page in the Manual makes it pretty clear that
> 
> 1. `local` statements introduce a local variable to a particular scope level in contrast with outer local variables of the same name.

Your wording is still confusing.

You can look up an English dictionary to find the meaning of `introduce`:

> to mention something for the first time in a piece of writing

The `first time` here is essentially the same as

> [@WalterMadelim](#):
>
> ```julia-auto
> help?> local
> local introduces a _new_ local variable.
> 
> ```

---

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 5:40am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/11 "2025-10-06T05:40:00Z")

</div>

Issue created

> <https://github.com/JuliaLang/julia/issues/59749>
>
> There is a serious confusion associated with \`local x\`.
> It's docstring reads vag…ue.
> or is actually the docstring is correct but the current julia's behavior is wrong? I don't know.
> Please see this discourse thread https://discourse.julialang.org/t/about-the-definition-of-local-keyword/132903/10?u=waltermadelim

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 5:42am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/12 "2025-10-06T05:42:01Z")

</div>

Again, none of that contradicts what I said from the start about multiple `local` statements in the same local scope level being redundant. They (plural) really do introduce _one_ new local variable to that scope. Nothing in the documentation shares your assertion that each individual statement must contribute a different local variable. Maybe it should assert the opposite, since your misinterpretation is fairly reasonable.

---

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 5:54am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/13 "2025-10-06T05:54:11Z")

</div>

I re-state my point:  
either the docstring definition is not correct, or the current julia behavior is wrong. (Now I believe that it is the former case).

e.g.

```julia
function unveil()
    let
        local iPhone_16
        iPhone_16 = 1
        local iPhone_16
        iPhone_16 = 2
    end
end

```

In the `let` block above, there is a name called `iPhone_16`.

Do all of us believe that there should be and must be _only one_ entity which is referred to by the name `iPhone_16`, within the `let` block?

If all of us believe so, then the docstring definition is wrong!  
because we already see `iPhone_16`, which is associating to `1` in the 4th line.

You cannot “introduce” `iPhone_16` in the 5th line because it is not new!  
You can introduce `iPhone_17` in that place though, which is indeed new.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 6:00am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/14 "2025-10-06T06:00:29Z")

</div>

Just occurred to me to ask, do you think declarations are _executed_ in order, like the assignments are?

---

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 6:19am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/15 "2025-10-06T06:19:12Z")

</div>

Suppose the parser reads my `function unveil()` above, and it discovers that there is one redundant `local iPhone_16`, okay suppose the parser removes one `local iPhone_16`.

Okay now it is fine.

But, Now review my first instance

> [@WalterMadelim](#):
>
> ```julia-auto
> julia> function f(a)
> local a
> end
> ERROR: syntax: local variable name "a" conflicts with an argument
> 
> ```

A fundamental question is:  
is the `a` in the “f(a)” **and** the `a` in the “local a” **the same name**?

If `local` is just declaring, not introducing, then why cannot the parser remove the `local a`???

I think these is no ambiguity here:

```julia
function simple(a)
    a
end

```

In the `simple` function, there is one and only one entity which is referred to by the _local_ name `a`.  
Given this fact, I think the declaration is redundant (because the `a` being an input arg, is already local). Anyone disagree?  
Following this logic, Why should the current julia throw an ERROR??

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 6:23am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/16 "2025-10-06T06:23:20Z")

</div>

> [@WalterMadelim](#):
>
> okay suppose the parser removes one `local iPhone_16`.

It demonstrably doesn’t do that, so not sure what to do with your reasoning following a false premise.

```julia-auto
julia> Meta.parse("""
       let
       local a
       local a
       end
       """)
:(let
      #= none:2 =#
      local a
      #= none:3 =#
      local a
  end)

```

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [October 6, 2025, 6:47am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/17 "2025-10-06T06:47:35Z")

</div>

> [@Benny](#):
>
> demonstrably doesn’t do that, so not sure what to do with your reasoning following a false premise.

I think @WalterMadelim was just a bit imprecise in his wording, and meant that some stage between “read source code” and “execution” has the effect of removing that “double declaration”. Possibly lowering, which sometimes is done in one step with parsing?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 6, 2025, 7:07am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/18 "2025-10-06T07:07:18Z")

</div>

> [@Sukera](#):
>
> Possibly lowering

I think so. Note that ALL `local`/`global` declarations disappear in lowered code after being applied to their scope level, so they cannot be executed in order like other code.

```julia-auto
julia> Meta.@lower let
        local a
        a = 1
        local a
        a = 2
       end
:($(Expr(:thunk, CodeInfo(
    @ REPL[1]:3 within `top-level scope`
1 ─ a = 1
│ @ REPL[1]:5 within `top-level scope`
│ a = 2
└── return 2
))))

julia> Meta.@lower let
        local a
        a = 1
        global a
       end
:($(Expr(:error, "variable \"a\" declared both local and global")))

```

---

<div class="post-metadata">

### Author: ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)
#### Post date: [October 6, 2025, 8:30am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/19 "2025-10-06T08:30:13Z")

</div>

> [@affans](#):
>
> so, within the scope of the function, you can certainly overwrite the function argument.

I suspect that there is something bad associated to overwriting/reusing a function arg.  
cf. [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured)  
The `abmult` is doing this bad thing.  
But `abmult2` changed a name `r0` stealthily. (I fail to see its motivation in the doc)

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [October 6, 2025, 9:11am UTC](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903/20 "2025-10-06T09:11:33Z")

</div>

> [@WalterMadelim](#):
>
> But `abmult2` changed a name `r0` stealthily. (I fail to see its motivation in the doc)

This is because the `r::Int = r0` declaration is necessary to introduce the type assertion on `r`. Contrary to popular believe, `::Int` in method signatures are NOT type assertions, they are (almost exclusively) relevant for selecting methods during dispatch. It is indeed confusing that they use the same syntax for different things.

[Next page](https://discourse.julialang.org/t/either-the-def-of-local-is-wrong-or-the-current-julia-behavior-is-unexpected/132903.md?page=2)
