# Unexpected behavior of global variables depending on function read/write behavior

**URL:** <https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [November 14, 2024, 10:26am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624 "2024-11-14T10:26:03Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 14, 2024, 10:26am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/1 "2024-11-14T10:26:03Z")

</div>

Hi,

I have been experimenting with the behavior of global variables in Julia.

I (perhaps incorrectly) believed the behavior was quite similar, if not exactly the same, as in Python.

Here’s some test code:

```julia
global x="x"
y="y"

function printtype()
    println("typeof(x)=$(typeof(x))")
    println("typeof(y)=$(typeof(y))")
end

function printxy()
    println("printxy: x=$(x)")
    println("printxy: y=$(y)")
end

function printxyglobal()
    global x
    global y
    println("printxyglobal: x=$(x)")
    println("printxyglobal: y=$(y)")
end

function changexy()
    println("changexy: x=$(x)") # added later
    if !@isdefined(x) # added later
        println("x is not defined") # added later
        println("x= $(x)") # added later
        println(x) # added later
    end # added later
    x = x == "x" ? "xx" : "x"
    y = y == "y" ? "yy" : "y"
    println("end of changexy") # added later
end

# FYI
function changexy_original()
    x = x == "x" ? "xx" : "x"
    y = y == "y" ? "yy" : "y"
end

function changexyglobal()
    global x
    global y
    x = x == "x" ? "xx" : "x"
    y = y == "y" ? "yy" : "y"
end

function changexytypeglobal()
    global x
    global y
    x = x == "x" ? 1 : "x"
    y = y == "y" ? 2 : "y"
end

println("printtype:")
printtype()

println("printxy:")
printxy()
println("printxyglobal:")
printxyglobal()

println("changexy:")
changexy()

println("printxy:")
printxy()
println("printxyglobal:")
printxyglobal()

println("changexyglobal:")
changexyglobal()

println("printxy:")
printxy()
println("printxyglobal:")
printxyglobal()

println("changexytypeglobal:")
changexytypeglobal()

println("printxy:")
printxy()
println("printxyglobal:")
printxyglobal()

println("done")

```

Here is the output:

```julia
$ julia global.jl
printtype:
typeof(x)=String
typeof(y)=String
printxy:
printxy: x=x
printxy: y=y
printxyglobal:
printxyglobal: x=x
printxyglobal: y=y
changexy:
ERROR: LoadError: UndefVarError: `x` not defined in local scope

```

If it wasn’t already obvious from running this code, what I find surprising is this:

- `printxy` is able to _read_ `x` and `y` without `global` (this is what I expect)
- `printxyglobal` behaves the same as `printxy` (again, exactly as I expect)
- `changexy` _ **cannot** _ read `x`! This appears to be in conflict with the behavior seen in `printxy`

The final bullet point is really the surprise. The first two are expected behaviors.

Is anyone able to help me understand why this happens?

I’m assuming I haven’t made a dumb mistake her or otherwise doing something obviously wrong?

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 14, 2024, 10:39am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/2 "2024-11-14T10:39:41Z")

</div>

> [@world-peace](#):
>
> - `printxy` is able to _read_ `x` and `y` without `global` (this is what I expect)
> - `printxyglobal` behaves the same as `printxy` (again, exactly as I expect)
> - `changexy` _ **cannot** _ read `x`! This appears to be in conflict with the behavior seen in `printxy`
> 
> The final bullet point is really the surprise. The first two are expected behaviors.

It’s because you assign to `x` in `changexy`, without declaring it as a global. The compiler sees the assignment and determines it is a local variable. However, at the point where it is read, it has not been defined yet. It’s just a local name which is not referring to anything yet. It’s like

```julia
julia> f() = (local x; println(x))
f (generic function with 1 method)

julia> f()
ERROR: UndefVarError: `x` not defined in local scope

```

or, even

```julia
julia> f() = (println(x); local x)

```

---

<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:** [November 14, 2024, 10:41am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/3 "2024-11-14T10:41:10Z")

</div>

The assignment in the function body treats the variable as a local variable by default. You need a `global` statement to override it. Python has the same rule:

```julia
>>> x = 1
>>> def foo():
... print("1: ", x)
... x = 2
... print("2: ", x)
...
>>> foo()
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    foo()
    ~~~^^
  File "<python-input-1>", line 2, in foo
    print("1: ", x)
                 ^
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
>>> def foo():
... global x
... print("1: ", x)
... x = 2
... print("2: ", x)
...
>>> foo()
1: 1
2: 2
>>> x
2

```

…though it’s worth pointing out there are other differences in rules. One difference is Python errors if the statement isn’t ahead of all the working code. Julia’s `global`/`local` statements apply to the entire scope it’s written in, regardless of which line except the final returning line where `global` without assignment errors. It’s better to not expect Julia to work like Python despite the relative similarities among other languages.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 14, 2024, 11:10am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/4 "2024-11-14T11:10:50Z")

</div>

I suspected it was something like that. Great! Thanks for confirming.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 14, 2024, 12:41pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/5 "2024-11-14T12:41:15Z")

</div>

For anyone reading this in future, the issue appears to be that the following line does not make much sense.

```julia
x = x == "x" ? "xx" : "x"

```

First, the value of `x` is compared against `"x"`. We have to ask the question, which `x`, or “what is `x`?” Since `x` has not been assigned to in the function, the answer is obvious. This refers to the global `x`, which exists outside of the function.

Next, having evaluated `x == "x" ? "xx" : "x"`, we can assign the result to `x`.

Again, we ask the question, to which `x` does this refer?

Since we are writing to a variable `x` and this variable has not been declared as `global x` at the beginning of our function, this `x` must be a new local variable `x`.

However, this statement conflicts with the previous statement where we concluded `x` was the global variable `x`.

Hence, this code is actually nonsensical.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [November 14, 2024, 6:51pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/6 "2024-11-14T18:51:06Z")

</div>

Just for fun, note that you can write

```julia-repl
julia> global x = "x"
"x"

julia> function f()
           let x = x
               x = x == "x" ? "xx" : "x"
               println(x)
           end
       end
f (generic function with 1 method)

julia> f()
xx

julia> x
"x"

```

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [November 14, 2024, 7:23pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/7 "2024-11-14T19:23:31Z")

</div>

> [@world-peace](#):
>
> declared as `global x` at the beginning of our function

`global` doesn’t have to be at the beginning.

```julia
julia> x=4
4

julia> function bar()
         x = 7
         global x
         return x
       end
bar (generic function with 1 method)

julia> bar(); @show x;
x = 7

```

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 15, 2024, 10:53am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/8 "2024-11-15T10:53:44Z")

</div>

True, but it _should_ be at the beginning of your function, to make it easier to understand.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [November 15, 2024, 4:21pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/9 "2024-11-15T16:21:23Z")

</div>

Of course. I just wanted to make it clear “For anyone reading this in future”.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 16, 2024, 10:22am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/10 "2024-11-16T10:22:54Z")

</div>

Your comment doesn’t make it clear at all. Quite the opposite. You’re telling people to do something that makes their code less clear.

For context, I commented something elsewhere a short time ago where I clarified something and started off my post with

> For anyone reading this in future

Hence why he’s quoted that.

Is there really any need for this kind of behavior?

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [November 16, 2024, 2:52pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/11 "2024-11-16T14:52:39Z")

</div>

Perhaps I’m being too terse. You posted a summary regarding scoping that included a small inaccuracy. There have been threads here before because of confusion from the position- independent nature of global. My intention was not to encourage moving global later but rather to warn that a later global can introduce unexpected behavior, thus the quote. I did not mean any offense and I’m sorry you took it that way.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 16, 2024, 3:03pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/12 "2024-11-16T15:03:20Z")

</div>

Seems pretty obvious that you were intending to mock me with your previous comment. Not sure how else someone would be expected to interpret that.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [November 16, 2024, 3:12pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/13 "2024-11-16T15:12:12Z")

</div>

I quoted you to indicate my intention of the previous post was to provide more information and hopefully dispel confusion for your future readers (intentionally not quoting you again), and not that I was suggesting a late global as you had interpreted it. I’ve already offered you an apology.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 16, 2024, 4:45pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/14 "2024-11-16T16:45:08Z")

</div>

> [@Jeff\_Emanuel](#):
>
> Of course. I just wanted to make it clear “For anyone reading this in future”.

I don’t think this was meant as a quote of @world-peace from another thread at all. This is a pretty standard expression that lots of people use on internet forums.

> [@world-peace](#):
>
> For context, I commented something elsewhere a short time ago where I clarified something and started off my post with
> 
> > For anyone reading this in future
> 
> Hence why he’s quoted that.

If @world-peace has the [same thread](https://discourse.julialang.org/t/asides-on-the-state-of-julia-for-scientific-machine-learning/122256/4) in mind as I do, then their wording was actually

> For the benefit of anyone reading this

which is not the same sentence that @Jeff_Emanuel used.

> [@world-peace](#):
>
> Seems pretty obvious that you were intending to mock me with your previous comment. Not sure how else someone would be expected to interpret that.

On this Discourse, please assume good intentions from the people you interact with, unless they have explicitly proved you wrong. I can’t recall observing mockery on this site, and I have no doubt @Jeff_Emanuel was genuinely trying to help.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [November 16, 2024, 5:04pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/15 "2024-11-16T17:04:16Z")

</div>

> [@gdalle](#):
>
> I don’t think this was meant as a quote of @world-peace from another thread at all.

I would assume it does refer to @world-peace 's

> [@world-peace](#):
>
> For anyone reading this in future, the issue appears to be that the following line does not make much sense.
> 
> `x = x == "x" ? "xx" : "x"`

from this thread.

I don’t think it’s too far-fetched to interpret @Jeff_Emanuel 's

> [@Jeff\_Emanuel](#):
>
> Of course. I just wanted to make it clear “For anyone reading this in future”.

as slightly mocking, but equally it could be interpreted as tongue-in-cheek. The medium of text just doesn’t lend itself to these kind of nuances (unless you add emoticons or stuff like /s.).

Anyway, @Jeff_Emanuel clarified that there was no ill-intent and apologised, so let’s just leave it at that and move on.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 16, 2024, 5:08pm UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/16 "2024-11-16T17:08:45Z")

</div>

> [@world-peace](#):
>
> For context, I commented something **elsewhere** a short time ago

@eldee perhaps you’re right. I might have over-interpreted the “elsewhere” here, thinking that it referred to another thread.  
In any case, that’s exactly the problem: we should all spend less time interpreting what everyone’s intentions are, and more time solving each other’s problems 🙂

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 18, 2024, 9:54am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/18 "2024-11-18T09:54:58Z")

</div>

I think it’s reasonable that I should be unhappy about this.

From my point of view, it appears that there is a double standard being applied here. I do not know why.

Previously my account has been banned for the most minor of faux-pas, but in this case it seems that for some reason not known to me, a technicality is being used to enable someone to mock someone else on the forums.

If I had posted this, I am pretty sure I would get banned again.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 18, 2024, 10:11am UTC](https://discourse.julialang.org/t/unexpected-behavior-of-global-variables-depending-on-function-read-write-behavior/122624/19 "2024-11-18T10:11:18Z")

</div>

> [@world-peace](#):
>
> From my point of view, it appears that there is a double standard being applied here. I do not know why.
> 
> Previously my account has been banned for the most minor of faux-pas, but in this case it seems that for some reason not known to me, a technicality is being used to enable someone to mock someone else on the forums.

Previous decisions by the moderation are not the subject here. We have already discussed those at length with you, both in public and in private. The same standards apply to everyone.

> [@world-peace](#):
>
> I think it’s reasonable that I should be unhappy about this.

You are entitled to your reactions. Meanwhile, @Jeff_Emanuel’s intent has been clarified and an olive branch has been extended. I suggest we collectively move on.
