# Confusing julia behavior. @everywhere macro changes the scope of local variables to global

**URL:** <https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436>\
**Category:** General Usage\
**Tags:** parallel, distributed, scope\
**Created:** [March 5, 2022, 5:38am UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436 "2022-03-05T05:38:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![singularity](https://avatars.discourse-cdn.com/v4/letter/s/898d66/32.png) [@singularity](https://discourse.julialang.org/u/singularity)\
**Post date:** [March 5, 2022, 5:38am UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436/1 "2022-03-05T05:38:57Z")

</div>

I just encountered a very confusing julia behavior. I always thought that variables defined inside a function remain local to that function. But in the following example, the scope changes.

I define a simple function as below

```julia
using Distributed
addprocs(2)

function f()
    @everywhere x = myid()
    @everywhere println("x = ", x)
end

```

Executing the following code

```julia
f()

```

gives the result

```julia
x = 1
From worker 2: x = 2
From worker 3: x = 3

```

But since x is defined inside the function, I would expect the variable `x` to be not defined outside the function. However, upon executing the following code

```julia
x

```

I get the result

```julia
1

```

Even more confusing is the execution of the following code

@fetchfrom 3 x

which again gives

```julia
1

```

This is super confusing behavior. First, how does x become available outside the function? Second, why are all the processors/cores returning the same value of x? This can create unintended memory leak issues. Thank you for your help.

---

<div class="post-metadata">

**Author:** ![lawless-m](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lawless-m/32/30869_2.png) [@lawless-m](https://discourse.julialang.org/u/lawless-m)\
**Post date:** [March 5, 2022, 6:49am UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436/2 "2022-03-05T06:49:09Z")

</div>

The documentation contradicts your assumptions regarding scope:

[`Distributed.@everywhere`](https://docs.julialang.org/en/v1/stdlib/Distributed/#Distributed.@everywhere) — Macro

```julia
@everywhere [procs()] expr

```

Execute an expression under `Main` on all `procs` .

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [March 5, 2022, 9:36am UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436/3 "2022-03-05T09:36:30Z")

</div>

What you want is probably

```julia
@everywhere function f()
    x = myid()
    println("x = ", x)
end

```

which makes the function available everywhere (the code gets evaluated in all `Main` modules). Followed by

```julia
@everywhere f()

```

which calls the function on every worker.

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [March 5, 2022, 9:49am UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436/4 "2022-03-05T09:49:16Z")

</div>

The `@fetchfrom` behaviour on a global variable on the other hand really baffles me, what is going on here?

```julia
using Distributed
addprocs(2)
@everywhere x = myid()
@everywhere println(x)
# 1
# From worker 2: 2
# From worker 3: 3
@fetchfrom 2 x
# returns 1
@everywhere println(x)
# 1
# From worker 2: 1 # this is now changed! :o
# From worker 3: 3

```

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [March 5, 2022, 10:06am UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436/5 "2022-03-05T10:06:05Z")

</div>

More importantly, it uses [`eval`](https://docs.julialang.org/en/v1/base/base/#Core.eval), which works in global scope.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [March 6, 2022, 7:18pm UTC](https://discourse.julialang.org/t/confusing-julia-behavior-everywhere-macro-changes-the-scope-of-local-variables-to-global/77436/6 "2022-03-06T19:18:03Z")

</div>

I find this a bit confusing as well. One thing that often adds clarity is to replace macros with the code executed. In this case:

```julia
julia> using MacroTools

julia> prettify(@macroexpand(@fetchfrom 2 x))
:(Distributed.remotecall_fetch((()->x), 2))

```

so `@fetchfrom 2 x` actually means

```julia
remotecall_fetch(() -> x, 2)

```

i.e. it creates a closure around `x`, and then executes the result on pid 2. I can see how that ends up returning 1 given the closure is created on pid 1 and therefore likely closes over the local `x`, but I’m not sure why it changes the value of `x` on pid 2.

The way to get the value of `x` from other processes is to directly ask for the symbol defined in `Main` on those processes, as described in [this](https://stackoverflow.com/questions/27677399/julia-how-to-copy-data-to-another-processor-in-julia?noredirect=1&lq=1) SO answer:

```julia
julia> @fetchfrom 3 getfield(Main, :x)
3

julia> @everywhere println(x)
1
      From worker 2:	2
      From worker 3:	3

```
