# Scope in functions

**URL:** https://discourse.julialang.org/t/scope-in-functions/22096
**Category:** General Usage
**Tags:** scope, functions
**Created:** [March 20, 2019, 9:55am UTC](https://discourse.julialang.org/t/scope-in-functions/22096 "2019-03-20T09:55:13Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![alee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alee/32/2954_2.png) [@alee](https://discourse.julialang.org/u/alee)
#### Post date: [March 20, 2019, 9:55am UTC](https://discourse.julialang.org/t/scope-in-functions/22096/1 "2019-03-20T09:55:13Z")

</div>

One of my collaborators found the following behaviour confusing.

```julia
function foo()
  function bar()
    x = 3
    return x
  end
  x = 1
  bar()
  return x
end

foo()

```

which outputs 3 (and not 1). This behaviour is different to some other common languages.

Is this related to “An assignment introducing a variable used inside a function, type or macro definition need not come before its inner usage…” in

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

In global scope, if one executes

```julia
function bar()
  x = 3
  return x
end
x = 1
bar()
x

```

then 1 is the output, not 3.

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [March 20, 2019, 10:06am UTC](https://discourse.julialang.org/t/scope-in-functions/22096/2 "2019-03-20T10:06:59Z")

</div>

In your first example `x` is a local variable and all three instances refer to the same `x`. In you second example, `x = 3` creates a local variable and `x = 1` a global. If you wanted the former to be global you’d have to state it `global x = 3`, then the output would be `3` again.

---

<div class="post-metadata">

### Author: ![alee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alee/32/2954_2.png) [@alee](https://discourse.julialang.org/u/alee)
#### Post date: [March 20, 2019, 12:00pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/3 "2019-03-20T12:00:58Z")

</div>

Thanks. I understand that ultimately all the instances refer to the same x, from the output.

The confusing part is that in the first example, the x in bar() actually modifies the x that is assigned _later_ in the same function. This is different behaviour to some other languages, e.g. R.

Also, if one was to write

```julia
function foo()
  function bar()
    local x = 3
    return x
  end
  x = 1
  bar()
  return x
end

foo()

```

then the output is 1, which is what some might expect from the first snippet as well.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 20, 2019, 12:15pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/4 "2019-03-20T12:15:25Z")

</div>

> [@alee](#):
>
> This is different behaviour to some other languages, e.g. R.

I don’t see why they should be similar — they are different languages, and in particular R has a very, ehem, [_interesting_ attitude to scope](http://adv-r.had.co.nz/Environments.html) that few other languages copy, and even seasoned R users do not particularly like.

---

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [March 20, 2019, 12:51pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/5 "2019-03-20T12:51:44Z")

</div>

> [@Tamas\_Papp](#):
>
> in particular R has a very, ehem, [_interesting_ attitude to scope](http://adv-r.had.co.nz/Environments.html) that few other languages copy, and even seasoned R users do not particularly like.

What the… I didn’t know about that 🙈

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [March 20, 2019, 12:56pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/6 "2019-03-20T12:56:39Z")

</div>

> [@alee](#):
>
> I understand that ultimately all the instances refer to the same x

No, in your second example the two `x` do not refer/bind to the same thing.

---

<div class="post-metadata">

### Author: ![alee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alee/32/2954_2.png) [@alee](https://discourse.julialang.org/u/alee)
#### Post date: [March 20, 2019, 2:07pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/7 "2019-03-20T14:07:25Z")

</div>

Hi, thanks for the responses. I do understand that the second example is different; that’s why I provided it.

I was not saying that the behaviour should be the same, or trying to start a discussion on differences in scoping more broadly, although I’m sure it would be interesting. I was just pointing out that the behaviour is different, so it is natural to want to understand why.

My question was:

Is this related to “An assignment introducing a variable used inside a function, type or macro definition need not come before its inner usage…” in

[Scope of Variables · The Julia Language](https://docs.julialang.org/en/v1/manual/variables-and-scoping/index.html) ?

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [March 20, 2019, 2:09pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/8 "2019-03-20T14:09:56Z")

</div>

No, it’s that global variables bindings you cannot change (unless you specify that you want it with a `global`; otherwise a new local variable is introduced on assignment) whereas local variable bindings you can change.

---

<div class="post-metadata">

### Author: ![septc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/septc/32/2980_2.png) [@septc](https://discourse.julialang.org/u/septc)
#### Post date: [March 20, 2019, 3:37pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/9 "2019-03-20T15:37:05Z")

</div>

Just for comparison, I’ve tried Python3 and Ruby for similar codes:

```python
def foo():
    def bar():
        x = 3
        return x
    #
    x = 1
    bar()
    print( "python: in foo():", x )
#

foo()

```

```python
def bar():
    x = 3
    return x
#

x = 1
bar()
print( "python3: top level:", x )

```

```ruby
def foo()
    def bar()
        x = 3
        return x
    end
    x = 1
    bar()
    puts( "ruby: in foo(): ", x )
end

foo()

```

```ruby
def bar()
    x = 3
    return x
end
x = 1
bar()
puts( "ruby: top level: ", x )

```

all of which give x = 1 (I hope the syntax above is correct though!) So I guess some people from those languages may also expect x to be 1. In my case, I use the “local” keyword whenever I’m not sure about the interpretation…

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [March 20, 2019, 4:06pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/10 "2019-03-20T16:06:45Z")

</div>

Python would be:

```julia

def foo():
    def bar():
        nonlocal x
        x = 3
        return x
    x = 1
    bar()
    print( "python: in foo():", x )

```

---

<div class="post-metadata">

### Author: ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)
#### Post date: [March 20, 2019, 4:38pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/11 "2019-03-20T16:38:07Z")

</div>

> [@alee](#):
>
> Is this related to “An assignment introducing a variable used inside a function, type or macro definition need not come before its inner usage…” in

Yes, it’s related to that. The scope of variables depends on the existence of assignments and `local` declarations in the scope, not on their order. This is intended to make scope more predictable; you can reorder statements within the same scope without changing the scopes of variables.

We also (like Scheme) allow assignments in inner functions to overwrite local variables in enclosing functions by default.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [March 20, 2019, 6:11pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/12 "2019-03-20T18:11:49Z")

</div>

In general we try hard to make meaning independent of order in a couple of different senses.

First, we strongly avoid making meaning depend on order of execution because it is inherently unpredictable. In this case it’s pretty simple but in general it is intractable (in the formal sense) to decide what will execute before what without actually executing it. Traditional dynamic languages have often been fine with allowing actual execution to determine semantics because they do almost no static analysis of code. A principle in the design of Julia is that the meaning of code should be statically resolvable, which helps both compilers and humans trying to understand the code.

Second, we also try to avoid syntactic order being significant where order is not inherently significant (c.f. it’s inherent to the order of expression evaluation). For example, we’ve been very careful to design things so that the order of import statements doesn’t matter (or more precisely, if you have a program that works without warnings and you reorder the import statements and the program still works without warnings, then it does the same thing). We’ve also been very careful to design things so that the order of method definitions doesn’t matter. This is because people like to reorganize their code by moving things around. And if that can cause subtle changes in meaning, that’s a huge gotcha.

The scope rule is very simple: assignment to `x` in a local scope means either

- if an `x` local variable exists in an outer scope, it updates it;
- if no `x` local variable exists, it creates and assigns `x`.

It does not matter if a local `x` in an outer scope is created or assigned before or after the assignment to `x` that we’re considering the meaning of—in both the syntactic and evaluation order sense of the word. In particular, this also means that these don’t affect the meaning of the code:

- if the assignment `x = 1` is syntactically before or after the definition of `bar`
- if the assignment `x = 1` is evaluated before or after the definition of `bar`

This means that you can move code around safely and put assignments in conditionals without fear of subtle changes of meaning.

---

<div class="post-metadata">

### Author: ![alee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alee/32/2954_2.png) [@alee](https://discourse.julialang.org/u/alee)
#### Post date: [March 20, 2019, 6:48pm UTC](https://discourse.julialang.org/t/scope-in-functions/22096/13 "2019-03-20T18:48:44Z")

</div>

Thanks very much for the detailed explanation!

---

<div class="post-metadata">

### Author: ![Leon\_Niceday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leon_niceday/32/216710_2.png) [@Leon\_Niceday](https://discourse.julialang.org/u/Leon_Niceday)
#### Post date: [May 17, 2025, 4:28am UTC](https://discourse.julialang.org/t/scope-in-functions/22096/14 "2025-05-17T04:28:40Z")

</div>

This post was temporarily hidden by the community for possibly being off-topic, unfocused, inappropriate, or spammy.
