# From "UndefVarError", a hopefully funny intro to Scoping

**URL:** <https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285>\
**Category:** New to Julia\
**Created:** [October 25, 2019, 4:41am UTC](https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285 "2019-10-25T04:41:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![HaoLi111](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haoli111/32/10982_2.png) [@HaoLi111](https://discourse.julialang.org/u/HaoLi111)\
**Post date:** [October 25, 2019, 4:41am UTC](https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285/1 "2019-10-25T04:41:25Z")

</div>

This is a translation version of the post from

> **[试写一个Julia Scoping作用域的中文讲解](https://discourse.juliacn.com/t/topic/1862)**
>
> 丢了的玩具-从UndefVarError说起 相信很多人遇到过著名的UndefVarError:变量未定义 9成情况下，肇事者写了这样一个程序，引起了Julia不满 #Scoping a=1 for i =1:20 a+=1 end 人家抱怨 UndefVarError: a not defined in top-level scope at base\\none in top-level scope at Scoping.jl:4 这是因为在一个for...

by myself. Hope it’s not too boring.

# First I declare that “Julia” refers to the language and is not associated with any person.

## The lost toy - the “UndefVarError”

If one orders Julia to do something with this:

```julia-auto
#Scoping
a=1
for i =1:20
    a+=1
end

```

then Julia will complain:

```julia-auto
UndefVarError: a not defined
in top-level scope at base\none
in top-level scope at Scoping.jl:4

```

which is because of the position of the variable. Imagine that the entire program store variables in a “Global Scope”. Now, in human language, if Julia is or was a baby, such behavior is, of course, not a problem. In fact, when Julia was less than 0.6 versions old, the variable gets everywhere (in the Global scope) and the room is quite messy.

After the good old days parents decide more reasonable behavior be practiced. Therefore, a for loop that is directly written uses its small “box” for the “toys” (variables). This is to make things more organized and sometimes make it play more happily without spending forever finding and grabbing the toys from nowhere.

It is possible to read and get the value from inside a for loop. That says, it is possible to have a glance of the entire room when Julia is sitting in the toy box.

```julia
a=1
for i =1:20
    println("$a")
end

```

and it does not matter how many layers of boxes

```julia-auto
x=1
for i = 1:10
    a=i^2
    println("a="*string(a))
    for j = 1:10
        println(i+j+a)
        println(x)
    end
end

```

But to physically reach it and do things to it, don’t stay in the box!

There are too solutions:

1. step out, locate the toy in the big room.

```julia-auto
a=1
for i = 1:20
    global a+=1
end
a

```

“global” is used to declare the operation. All happy.

However, if there is only one toy in the room, why sitting in an empty box? Why not create a larger box to include the poor toy(if I can afford cardboard)？

```julia-auto
let
a=1
for i = 1:20
    a+=1
end
a
end

```

Use “let-end” block to let the variable in. “who cares about the empty one?”

## The problems of let-end block

Then things go bad. If we can throw away the small boxes, who is in charge of tidying up the room??  
Actually there were a lot of arguments…  
Now don’t worry about this…

> <https://github.com/JuliaLang/julia/issues/423>
>
> Hello Julia developers,
> 
> congratulations with your great new language. I was sin…ging 'O Julia' out loud all day yesterday.
> 
> But now my bug report. Notwithstanding the \`let\`, \`global\` and \`local\` keywords, it seems there is not always a clear distinction in Julia between variable declaration and assignment. This breaks encapsulation and can lead to hard to find bugs.
> 
> \`\`\`
> function some\_scope()
> ...
> ... many lines of code
> ...
> f = () -\> x = 42 # Not clear if this declares a local variable or assigns to one from the enclosing scope.
> end
> \`\`\`
> 
> Matlab's scoping rules we don't even need to discuss \[1\], Coffeescript is a disaster \[2\], please don't copy Ruby on this one \[3\], Perl and Javascript are ok as long as you don't forget your \`my\`'s and \`var\`'s (or use strict), Python fixed it in version 3 \[4\], and one could say Scheme got it right the first time in 1970 \[5\].
> 
> What is the reasoning behind Julia's intricate scoping rules?
> 
> \[1\] http://www.mathworks.nl/help/techdoc/matlab\_prog/f4-39683.html#f4-73993
> \[2\] https://github.com/jashkenas/coffee-script/issues/712
> \[3\] http://www.rubyist.net/~matz/slides/rc2003/mgp00010.html
> \[4\] http://www.python.org/dev/peps/pep-3104/
> \[5\] http://news.ycombinator.com/item?id=3379962

I said nothing.

## Use of “local”

Alright let’s face it, Julia is growing up.

Considering 2 examples:

```julia-auto
a=1
for i = 1:10
    global a = 1
    global a = a+i
    show(a)
end
a

a=1
for i = 1:10
    local a = 1
    local a = a+i
    show(a)
end
a

```

The local variable will only be used within its scope, whereas the brute “global” affect the global variable.  
This seems unimportant, but this is about toy, who knows what weapons Julia will play with in the future?

## Types of scopes, and how to be in charge

Now we gotta be careful about this:

There are mainly 3 types of scoping  
global - global scope  
function - function scope  
for,while - soft scope  
Why is it soft? Because “global” and “local” can break it!  
function isolates its own set of variables, like a fancy version of organizer. To make it more fancy you can organize these organizers with modules and packages–but that’s too much for today’s story.

## No global in functions!

So functions are special. They return values, but usually do not change it–unless the structure is complicated and when the parameter get passed by indices.

In functions, there is no need to write globals-- the parents are nicer here. And in fact, writing global will mean putting things into the global scope, which is not allowed (remember Julia’s cousin R did this and ended up in the hospital).

A function does not change this outer single value(when it is in a good temper).

```julia-auto
function f(x)
    for i in 1:3
        x=x^2
    end
    return x
end

f(2)

```

But occasionally it gets mad.

the function times2() works without changing anything in the global scope here

```julia-auto
x = [1 2;3 4]
x

function times2(x::Array)
    x*2
end

times2(x)
x

```

But its second brother times2!() gets quite angry

```julia-auto
function times2!(x::Array)
    x[:,:] = x[:,:].*2
    return x
end
times2!(x)
x

```

If you run this, notice that it changes the x value outside.

But then how do I know if a function (or macro) is angry?

Note that they all have “!”

```julia-auto
append!() sort!()
plot!() point()

```

if you don’t want to change the original value, use the peaceful version without “!”.

It is worthy to notice, that deleting the “!” does not calm this down

assigning a different variable name works neither, as it does not change the essential way that messages are passed.

```julia-auto

function times2_2!(x::Array)
    y=x
    y[:,:] = x[:,:]*2
    return x
end

x
times2_2!(x)
x

```

This is useless.  
In this case, maybe copy another version

```julia-auto
function times2_3(x::Array)
    y = copy(x)
    y[:,:] *=2
    return y
end

x
times2_3(x)
x

```

## A Quiz

Now, find the bug hidden in the toy

```julia-auto
for i in 1:10
    for j in 1:10
        global a =i*j
    end
    if i*j>1
        show(1)
    end
end

```

See that?  
Play with the toys, not the toy containers.

---

<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:** [October 25, 2019, 5:21am UTC](https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285/2 "2019-10-25T05:21:01Z")

</div>

The best place for these kind of posts if a blog — please consider starting one, and submit it to

> **[juliabloggers.com | A Julia Language Blog Aggregator](https://www.juliabloggers.com/)**
>
> A Julia Language Blog Aggregator

then it will be aggregated in the RSS feed.

---

<div class="post-metadata">

**Author:** ![HaoLi111](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haoli111/32/10982_2.png) [@HaoLi111](https://discourse.julialang.org/u/HaoLi111)\
**Post date:** [October 25, 2019, 5:35am UTC](https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285/3 "2019-10-25T05:35:31Z")

</div>

Hi thanks for the suggestion. For this, if I start a blog, do I delete the origional post in the discussion and paste it onto the blog and then send the RSS feed?  
Thanks in advance.

---

<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:** [October 25, 2019, 5:56am UTC](https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285/4 "2019-10-25T05:56:19Z")

</div>

I was just suggesting a blog as the best place for future posts like this.

---

<div class="post-metadata">

**Author:** ![HaoLi111](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haoli111/32/10982_2.png) [@HaoLi111](https://discourse.julialang.org/u/HaoLi111)\
**Post date:** [October 25, 2019, 9:10am UTC](https://discourse.julialang.org/t/from-undefvarerror-a-hopefully-funny-intro-to-scoping/30285/5 "2019-10-25T09:10:11Z")

</div>

OK. Got it. Thanks
