# Scopes: accessing a global variable hidden by a local of the same name

**URL:** <https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253>\
**Category:** New to Julia\
**Tags:** question, scope\
**Created:** [December 7, 2023, 5:18am UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253 "2023-12-07T05:18:28Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [December 7, 2023, 5:18am UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/1 "2023-12-07T05:18:28Z")

</div>

I’m not exactly “new to Julia” but I thought this would belong here.

How do you access a global variable hidden by a local variable of the same name? Reading the documentation (see the bottom of this message), I got the impression that `global x` was the way, but I found that it’s an error once the global `x` is hidden by the local one.

By just a guess, I discovered that `Main.x` is accessible. So, is this the “official” way? Or is there a standard way to refer to the outer scope? Here is a sample code:

```julia
x = 123
function func(x)
  @show x
  x = "hello"
  @show x
# global x += 321 # -> MethodError: no method matching +(::String, ::Int64)
  Main.x += 321
  @show x
  @show Main.x
end
func(3.14)

```

[Now, please don’t mention 1) that using the same name is a bad practice or 2) that modifying a global variable is a bad design. I know that this is a bad practice and it’s a bad design _in general_. But, I have a legitimate use for this, but to describe it would double the length of this message. 🙂 So, please assume that I know what I’m doing. 🙂]

[https://docs.julialang.org/en/v1/manual/variables-and-scoping/](https://docs.julialang.org/en/v1/manual/variables-and-scoping/)

---

<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:** [December 7, 2023, 8:31am UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/2 "2023-12-07T08:31:39Z")

</div>

If you uncomment that line in your example, the global `x` is not hidden. The `global x` declaration does not occur in order at runtime, it applies across the whole scope at parse-time, so what happened was you reassigned the global `x` at `x = "hello"`, then the `+` fails. You can check the global `x` after the call.

The difference between declaring `global x` and `Main.x` is that the former accesses the enclosing module but the latter accesses the specified module `Main`. You could try `@ __MODULE__ ` to expand to the enclosing module. You’re restricted from assigning variables in arbitrarily specified modules, so you’ll need to work around that with ~~`@eval(@ __MODULE__ , x+=321)`~~ `@eval x+=321`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 7, 2023, 2:24pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/3 "2023-12-07T14:24:16Z")

</div>

> [@ryofurue](#):
>
> By just a guess, I discovered that `Main.x` is accessible. So, is this the “official” way?

That only works if the global variable is in the `Main` module, e.g. if you are running the code in the REPL. It won’t work in any other module. But if you know what module `Foo` the global symbol is defined in, you can reference it as `Foo.x`.

The more common solution is to rename your local variables so that they don’t conflict with any global symbols you want to access. For example, if you want to call the [`sum`](https://docs.julialang.org/en/v1/base/collections/#Base.sum) function, but also have a local variable named `sum`, you can either call `sum(...)` via `Base.sum(...)` or rename your local variable (e.g. to `s`).

If you are getting these local variables by code generation / metaprogramming (which you should [rarely do](https://discourse.julialang.org/t/how-to-warn-new-users-away-from-metaprogramming/35022/22)), then you need to be careful of [“hygiene”](https://en.wikipedia.org/wiki/Hygienic_macro) — don’t generate variable names like `x`, but instead use [`gensym()`](https://docs.julialang.org/en/v1/base/base/#Base.gensym) or similar to generate unique local-variable names. If the generated local-variable names come from an external source pass them through `gensym` to hygienize them. (A Julia `macro` does this for you automatically.)

> [@ryofurue](#):
>
> But, I have a legitimate use for this, but to describe it would double the length of this message.

By not including this context, you have probably doubled the work of the people trying to respond to you, because now we have to guess at things like “where does the conflict come from?”, “why can’t you just rename your local variable?”, and “do you know the module where the global symbol is defined?” in order to answer your question in several different scenarios.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [December 7, 2023, 4:10pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/4 "2023-12-07T16:10:06Z")

</div>

> [@Benny](#):
>
> You could try `@ __MODULE__ ` to expand to the enclosing module. You’re restricted from assigning variables in arbitrarily specified modules, so you’ll need to work around that with `@eval(@ __MODULE__ , x+=321)`.

If I understand the docstring correctly, passing `@ __MODULE__ ` to `@eval` is redundant; this is already the default behavior:

```julia-repl
  eval(expr)

  Evaluate an expression in the global scope of the containing module. [...]

```

So the easiest solution is perhaps just a plain `@eval`:

```julia-repl
julia> x = 123
123

julia> function func(x)
         @show x
         x = "hello"
         @show x
         @eval x += 321
         @show x
         @show @eval x
       end
func (generic function with 1 method)

julia> func(3.14)
x = 3.14
x = "hello"
x = "hello"
#= REPL[2]:7 =# @eval(x) = 444
444

julia> module A
           x = 456
           function func(x)
               @show x
               x = "hello"
               @show x
               @eval x += 321
               @show x
               @show @eval x
           end
       end
Main.A

julia> A.func(3.14)
x = 3.14
x = "hello"
x = "hello"
#= REPL[4]:9 =# @eval(x) = 777
777

```

---

<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:** [December 7, 2023, 4:38pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/5 "2023-12-07T16:38:47Z")

</div>

> [@danielwe](#):
>
> If I understand the docstring correctly, passing `@ __MODULE__ ` to `@eval` is redundant; this is already the default behavior:
> 
> ```julia
> eval(expr)
> 
> ```

`@eval` expands to `Core.eval(mod, expr)`, not the module-wise `eval(expr)`, but you’re right that `@eval` defaults to the enclosing scope the same way the module-wise `eval` runs `Core.eval` in the enclosing scope, idk why it slipped my mind.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [December 8, 2023, 4:20pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/6 "2023-12-08T16:20:24Z")

</div>

Thank you everybody for the helpful discussion. I know understand that either `eval` or `Modulename.x` is the way to go.

Also, I understand it correctly, `global x` hides the local `x` entirely within the scope. So, a new question, purely out of curiosity without any practical use, is: How can you access the local `x`?

```julia
x = 123
function func(x)
  global x
  # Are you able to get the value
  # of the parameter to this function here in this scope?
end

```

By the way

> [@stevengj](#):
>
> The more common solution is to rename your local variables so that they don’t conflict with any global symbols you want to access.

Of course! That’s what I (and everybody) do 99% of the time. I don’t use the same name without a reason. As I said in my initial message, to explain the scenario with a complete context would take a lot of space, but a shorter version of explanation is this:

```julia
module Mymod
soundspeed = 340.0 # m/s, default value
meantemp = 20.0 # ℃, default value
function set_pars(; soundspeed = nothing, meantemp = nothing)
  (! isnothing(soundspeed)) && Mymod.soundspeed = soundspeed
  (! isnothing(meantemp)) && Mymod.meantemp = meantemp
end
# . . . some functions to export . . .
end

# --- main program
import Mymod
Mymod.set_pars(soundspeed = 300.0)

```

Because these names are standard throughout the project, there is no motivation to come up with variant names. You _could_ argue that

```julia
soundspeed_ = 340.0
meantemp_ = 20.0
function func(; soundspeed = nothing, meantemp = nothing)
  (! isnothing(soundspeed)) && soundspeed_ = soundspeed
  . . .

```

would be better, but I don’t necessarily agree with that, because the first code is perfectly clear and my modules often start out as a stand-alone program: I turn a program into a module when the functions in it turn out to be useful in other programs. In such a case, I want to minimize the modification to it.

Whether we should use global variables like that is another issue. When two parallel threads use the same module and try to modify the same global variables . . . I have no experience in parallel programming and I don’t think my little programs and modules will be used in parallelized programs.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [December 8, 2023, 4:32pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/7 "2023-12-08T16:32:36Z")

</div>

For completeness, I just realized there are functions `getglobal` and `setglobal!`, which also accomplish what you asked for. See docs for `setglobal!` here: [Essentials · The Julia Language](https://docs.julialang.org/en/v1/base/base/#Core.setglobal!). But note the final comment:

> Users will typically access this functionality through the [`setproperty!`](https://docs.julialang.org/en/v1/base/base/#Base.setproperty!) function or corresponding syntax (i.e. `module.name = x`) instead, so this is intended only for very specific use cases.

Sounds like `Mymod.soundspeed` is the sanctioned way.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 8, 2023, 5:22pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/8 "2023-12-08T17:22:19Z")

</div>

> [@ryofurue](#):
>
> ```julia
> module Mymod
> soundspeed = 340.0 # m/s, default value
> meantemp = 20.0 # ℃, default value
> function set_pars(; soundspeed = nothing, meantemp = nothing)
> (! isnothing(soundspeed)) && Mymod.soundspeed = soundspeed
> 
> ```

This can be written just as:

```julia
module Mymod
soundspeed = 340.0 # m/s, default value
meantemp = 20.0 # ℃, default value
function set_pars(; soundspeed = soundspeed, meantemp = meantemp)

```

And you don´t need to mess around with any of that, with the additional important advantage of not using global variables in your functions anymore.

You could rename the default parameters to `default_soundspeed` and `default_meantemp` to use `set_pars(; soundspeed=default_soundspeed...`), and it would be very clear.

Maybe useful, you can also put all parameters in a struct with default values, such as:

```julia
julia> @kwdef struct Parameters
           soundspeed::Float64 = 1.0
           meantemp::Float64 = 300.0
       end
Parameters

julia> function f(; pars = Parameters())
           return pars.soundspeed, pars.meantemp
       end
f (generic function with 1 method)

julia> f()
(1.0, 300.0)

julia> f(;pars = Parameters(meantemp=500.0))
(1.0, 500.0)

```

> [@ryofurue](#):
>
> Whether we should use global variables like that is another issue.

I think it is a perfectly good advice that you should never use global variables, ever. Before giving up and using one, think ten times. There are not many situations in which the code without them are worst.

---

<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:** [December 8, 2023, 5:41pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/9 "2023-12-08T17:41:41Z")

</div>

> [@ryofurue](#):
>
> How can you access the local `x`?

You don’t, `global x` basically erases its existence in its scope. You are aware that this is considered “bad practice” so it shouldn’t be surprising that difficult restrictions show up.

> [@ryofurue](#):
>
> Because these names are standard throughout the project, there is no motivation to come up with variant names.

It’s standard practice to vary the names so they can coexist without conflict. I’d keep the unembellished name for the global variables accessible to all enclosing scopes, save `soundspeed_`, `soundspeed1`, etc for function bodies.

> [@danielwe](#):
>
> Sounds like `Mymod.soundspeed` is the sanctioned way.

Interesting, they changed this in v1.9, `setproperty!` on modules used to call `setfield!` to error.

> [@lmiq](#):
>
> I think it is a perfectly good advice that you should never use global variables, ever.

I don’t know about “never”, after all base Julia has a few like `pi`. It’s more like when you don’t have the excuse of mathematical or physical constants, pass data through arguments as much as possible, then there’s alternate ways for outer variables to make it into functions with untyped globals dead last on the list.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 8, 2023, 6:28pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/10 "2023-12-08T18:28:47Z")

</div>

> [@Benny](#):
>
> I don’t know about “never”, after all base Julia has a few like `pi`. It’s more like when you don’t have the excuse of mathematical or physical constants

Yes, never is an exaggeration, but even physical constants can change units or one may want to vary them to make tests, and having them as parameters ends up being practical.

---

<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:** [December 8, 2023, 6:43pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/11 "2023-12-08T18:43:59Z")

</div>

All these suggestions are far more complicated than what I’d do: create a separate scope.

```julia-repl
julia> x = 123
123

julia> function func(x)
         @show x
         x = "hello"
         @show x
         let # create a separate scope!
           @show x # because we define x as global in this scope (yes, even "after" this line), this is the global
           global x += 321
           @show x
         end
         @show x
       end
func (generic function with 1 method)

julia> func(pi)
x = π
x = "hello"
x = 123
x = 444
x = "hello"
"hello"

```

Note that `let` blocks evaluate to the result of their last expression, so in this way you can simply “exfiltrate” the global back to your original scope more succinctly:

```julia-repl
julia> function local_times_global(x)
           x_global = let
               global x
               x
           end
           x * x_global
       end
local_times_global (generic function with 1 method)

julia> x = 123
123

julia> local_times_global(2)
246

```

But, yeah, I also agree that this isn’t ideal and will likely confuse even future-you and it’s better to avoid globals in the first place.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [December 9, 2023, 1:11pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/12 "2023-12-09T13:11:29Z")

</div>

[quote=“lmiq, post:8, topic:107253”]

> [@ryofurue](#):
>
> ```julia
> module Mymodsoundspeed = 340.0 # m/s, default valuemeantemp = 20.0 # ℃, default valuefunction set_pars(; soundspeed = nothing, meantemp = nothing) (! isnothing(soundspeed)) && Mymod.soundspeed = soundspeed
> (! isnothing(meantemp)) && Mymod.meantemp = meantemp
> end
> # . . . some functions to export . . .
> end
> 
> # --- main program
> import Mymod
> Mymod.set_pars(soundspeed = 300.0)
> 
> ```
> 
> This can be written just as:
> 
> ```julia
> module Mymod
> soundspeed = 340.0 # m/s, default value
> meantemp = 20.0 # ℃, default value
> function set_pars(; soundspeed = soundspeed, meantemp = meantemp)
> 
> ```
> 
> . . .  
> You could rename the default parameters to `default_soundspeed` and `default_meantemp` to use `set_pars(; soundspeed=default_soundspeed...` ), and it would be very clear.

I didn’t foresee that this misunderstanding would happen!! I didn’t mean it that way.

When I wrote “default value”, I meant 20℃, not `meantemp`:

```julia
module Mymod
soundspeed = 340.0 # m/s, its default value is 340.0 m/s
meantemp = 20.0 # ℃, its default value is 20.0℃

"Function to change the module-global parameters"
function set_pars(; soundspeed = nothing, meantemp = nothing)
  (! isnothing(soundspeed)) && (Mymod.soundspeed = soundspeed)
  (! isnothing(meantemp)) && (Mymod.meantemp = meantemp)
end
# . . . some functions that depend on the module global parameters . . .
function printvalues()
  @show soundspeed
  @show meantemp
end
#. . . some more functions . . .
end

# --- main program
Mymod.printvalues()
Mymod.set_pars(soundspeed = 222.2)
Mymod.printvalues()

end

# --- main program
import Mymod
Mymod.printvalues()
Mymod.set_pars(soundspeed = 300.0)
Mymod.printvalues()

```

As you can see (I hope), I want to provide a function to change those module-global variables.

. . . This was the very reason why I was _very_ reluctant to say what I was doing! It takes a log of careful writing to clearly explain the context and intention and such a writing would be long.

I just asked what’s the standard way to modify a module-global variable when there is a local variable of the same name. It’s a very clear technical question, which should have a clear technical answer.

> [@](#):
>
> Maybe useful, you can also put all parameters in a struct with default values, such as:
> 
> julia\> @kwdef struct Parameters  
> soundspeed::Float64 = 1.0  
> meantemp::Float64 = 300.0  
> end  
> Parameters
> 
> julia\> function f(; pars = Parameters())  
> return pars.soundspeed, pars.meantemp  
> end

Yes! If I have to discuss the issue fully, I would mention that style.

There are several possibilities to manage parameters which are shared by a set of functions and which you need to change occasionally. Your method above is one of them. My method is another. There are cons and pros in each.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 9, 2023, 1:21pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/13 "2023-12-09T13:21:25Z")

</div>

> [@ryofurue](#):
>
> ), I want to provide a function to change those module-global variables.

Then your values cannot be `const` values, and you’ll have probably enormous performance issues.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [December 9, 2023, 1:48pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/14 "2023-12-09T13:48:51Z")

</div>

> [@lmiq](#):
>
> Then your values cannot be `const` values, and you’ll have probably enormous performance issues.

Trust me that I’m aware of performance implications of non-const global variables. You are not able to estimate the size of the potential performance issues because you haven’t measured that of my code.

When my code is too slow, I optimize. That’s all. I don’t avoid global variables before measuring the performance.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 9, 2023, 3:05pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/15 "2023-12-09T15:05:57Z")

</div>

No need to take it personally. More often than not unusual questions reveal bad design patterns, and we cannot know the background of everyone.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [December 9, 2023, 7:16pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/16 "2023-12-09T19:16:36Z")

</div>

The performance issue is easily ~~fixed~~ improved by declaring the type of the global variables:

```julia
module Mymod
soundspeed::Float64 = 340.0 # m/s, its default value is 340.0 m/s
meantemp::Float64 = 20.0 # ℃, its default value is 20.0℃
...
end

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 9, 2023, 7:33pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/17 "2023-12-09T19:33:07Z")

</div>

Is it completely? I’ve seen many examples where typing the globals did not reproduce the performance of local variables, or global consts. I imagine that a typed global is still a heap allocated object, thus it can be optimized to the same level as an immutable local value. Correct me if I’m wrong.

---

<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:** [December 9, 2023, 7:43pm UTC](https://discourse.julialang.org/t/scopes-accessing-a-global-variable-hidden-by-a-local-of-the-same-name/107253/18 "2023-12-09T19:43:56Z")

</div>

The type stability definitely helps, but yeah there’s extra work in retrieving the value from the heap. I don’t know if dereferencing happens every time the variable is used or if the compiler tries to reduce it, I would need to learn how to read `@code_llvm`. There’s an extra layer to it where a typed global`::T` need [more dereferencing](https://discourse.julialang.org/t/why-is-accessing-a-typed-global-different-from-dereferencing-a-const-ref/102992/11) than a `const` `Ref{T}`.
