# Scope of variable

**URL:** <https://discourse.julialang.org/t/scope-of-variable/43396>\
**Category:** General Usage\
**Created:** [July 20, 2020, 7:04pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396 "2020-07-20T19:04:31Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [July 20, 2020, 7:04pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/1 "2020-07-20T19:04:32Z")

</div>

This code runs as expected when `let` block is uncommented:

```julia
using AbstractPlotting, GLMakie
using GLMakie.GLFW
using GLMakie: to_native

# let 
  npoints = 10
  points = Node(Point3f0.(rand(npoints), rand(npoints), rand(npoints)))
  scene = Scene(limits = FRect3D(Vec3f0(0), Vec3f0(1)), resolution = (1200, 1200), camera = cam3d!, show_axis = false)
  scatter!(scene, points)
  window = to_native(display(scene)) 
  GLFW.SetWindowTitle(window, "Test $npoints")

  on(events(scene).keyboardbuttons) do key
    ispressed(key, Keyboard.escape) && GLFW.SetWindowShouldClose(window, true) 
    ispressed(key, Keyboard.page_down) && (npoints = max(2, npoints-1))
    ispressed(key, Keyboard.page_up) && (npoints += 1)
    GLFW.SetWindowTitle(window, "Test $npoints")
    points[] = Point3f0.(rand(npoints), rand(npoints), rand(npoints))
  end
# end

```

but when it is commented, I’m getting:

```julia
UndefVarError: npoints not defined

```

Why is that?

---

<div class="post-metadata">

**Author:** ![Chong\_Wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chong_wang/32/20307_2.png) [@Chong\_Wang](https://discourse.julialang.org/u/Chong_Wang)\
**Post date:** [July 20, 2020, 7:18pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/2 "2020-07-20T19:18:17Z")

</div>

Global variables cannot be changed in do blocks?

[https://github.com/JuliaLang/julia/issues/28789](https://github.com/JuliaLang/julia/issues/28789)

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 20, 2020, 7:20pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/3 "2020-07-20T19:20:43Z")

</div>

`do` is just syntax for an anonymous function, so you are still in local scope inside `do` blocks

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [July 20, 2020, 7:26pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/4 "2020-07-20T19:26:16Z")

</div>

I don’t get it. Do I have to annotate `npoints` somehow to make it visible inside an anonymous function, in case there is no `let` block?

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 20, 2020, 7:29pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/5 "2020-07-20T19:29:52Z")

</div>

Yes if there is no `let` block you have to put `global npoints` somewhere, or place `npoints` inside some sort of `mutable struct` or `Ref`.

But why not just keep the `let` block? Or put your code into a function?

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [July 20, 2020, 7:35pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/6 "2020-07-20T19:35:07Z")

</div>

> [@pdeffebach](#):
>
> you have to put `global npoints` somewhere

When I use:

```julia
  global npoints = 10

```

I get the same error.

> [@pdeffebach](#):
>
> But why not just keep the `let` block?

That is what I started with, but then I run into benchmarking issues: [Unintuitive behaviour with BenchmarkTools](https://discourse.julialang.org/t/unintuitive-behaviour-with-benchmarktools/43291)

**EDIT**

I misunderstood your suggestion. Putting `global npoints` inside the `do` block solves the problem.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [July 20, 2020, 7:42pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/7 "2020-07-20T19:42:04Z")

</div>

The `let` and `do` here are red herrings. Here are some simpler questions to nudge you in the right direction.

Let’s say I have:

```julia
function foo()
  x = ...
end

```

This unambiguously creates a local variable named `x` inside `foo()`, right?

Now let’s say I have:

```julia
function foo()
  println(x)
end

```

This unambiguously refers to some (hopefully existing) global variable named `x`, right?

Now what if I have:

```julia
function foo()
  x = x + 1
end

```

What is `x`? If we follow the first example, it’s a local variable, but then the right-hand side makes no sense since that local variable doesn’t exist yet. If we follow the second example, then it’s a global variable, but now we are silently modifying a global variable, which the language does not allow. If we follow both examples, somehow `x` is both a local and a global variable at the same time, which is even worse. That’s why this situation is an error in Julia, since there’s no obviously right thing to do.

If you want `x` to refer to the global variable, then you need:

```julia
function foo()
  global x
  x = x + 1
end

```

That works with no issues. If you want x to be a local variable, then you can’t also have it refer to the global variable with the same name.

A `let` block creates a new _local_ scope, so you _can_ do:

```julia
julia> let 
         a = 1 
         function foo()
           a = a + 1 # updates `a` in the parent local scope. 
         end
         foo()
         println(a)
       end
2

```

as explained in [Scope of Variables · The Julia Language](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope-1)

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pauljurczak/32/921_2.png) [@pauljurczak](https://discourse.julialang.org/u/pauljurczak)\
**Post date:** [July 20, 2020, 7:59pm UTC](https://discourse.julialang.org/t/scope-of-variable/43396/8 "2020-07-20T19:59:16Z")

</div>

> [@rdeits](#):
>
> The `let` and `do` here are red herrings. Here are some simpler questions to nudge you in the right direction.

Thank you. This issue crossed my mind the first time I wrote

```julia
npoints = max(2, npoints-1)

```

but it magically worked (I had `let` block), so I forgot about it. The special treatment of global scope takes time to get used to.
