# Scoping rules for try - catch - finally

**URL:** <https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617>\
**Category:** New to Julia\
**Created:** [December 23, 2019, 10:33am UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617 "2019-12-23T10:33:49Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 23, 2019, 10:33am UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/1 "2019-12-23T10:33:50Z")

</div>

I understand that try-catch-finally construct introduces ist own local scope (_soft local scope_ according to [https://michaelhatherly.github.io/julia-docs/en/latest/manual/variables-and-scoping.html](https://michaelhatherly.github.io/julia-docs/en/latest/manual/variables-and-scoping.html) ). Now I want to do some processing with try/catch/finally AND pass the results to the outer scope. Something like this:

```julia
x = 0
y = 0
er = false # or true for another branch

try
    if er
        x = 1
        error()
    else
        x = 2
    end
catch
    x *= 10
finally
    # x *= 100 ### this line would produce an error:
    #### x from try/catch ist not available in finally 
    y = 300
end

println("x=",x, " y=", y)

```

`x =0 y=0`

For results from `try`/`catch` not available in the `finally` see discussion in [Cumbersome scoping rules for try - catch - finally](https://discourse.julialang.org/t/cumbersome-scoping-rules-for-try-catch-finally/4582) .

For thist last thing, I could somehow circumwent it by using let block:

```julia
let
    x = 0
    y = 0
    er = true # or false for another branch

    try
        if er
            x = 1
            error()
        else
            x = 2
        end
    catch
        x *= 10
    finally
        x *= 100
        y = 300
    end

println("x=",x, " y=", y)
end

println("x=",x, " y=", y)

```

` x=1000 y=300 x=0 y=0`

Any idea how to pass the results to the outer scope?

---

<div class="post-metadata">

**Author:** ![Sijun](https://avatars.discourse-cdn.com/v4/letter/s/b2d939/32.png) [@Sijun](https://discourse.julialang.org/u/Sijun)\
**Post date:** [December 23, 2019, 11:19am UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/2 "2019-12-23T11:19:15Z")

</div>

In the first code, those `x`s and `y`s inside try catch blocks are all local variables. So `global` keyword must be prepended to them:

```julia
try
    if er
        global x = 1
        error()
    else
        global x = 2
    end
catch
    global x *= 10
finally
    # x *= 100 ### this line would produce an error:
    #### x from try/catch ist not available in finally 
    global y = 300
end

```

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 23, 2019, 11:37am UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/3 "2019-12-23T11:37:48Z")

</div>

@Sijun thank you!

Do I understand you correctly that in this case _x_ and _y_ are “really global”, i.e. avaliable across all files? If yes, I would give the variables some long obscure name and live with it, but actually it would be nice to have them available in the outer scope of the try block (i.e. in this module/function etc.) only. Could that be done, or is it currently a limitation of the language?

---

<div class="post-metadata">

**Author:** ![Sijun](https://avatars.discourse-cdn.com/v4/letter/s/b2d939/32.png) [@Sijun](https://discourse.julialang.org/u/Sijun)\
**Post date:** [December 23, 2019, 11:47am UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/4 "2019-12-23T11:47:58Z")

</div>

The scope of global variables are limited to the immediate module they belong to.

```julia
module OuterModule
   x = 1
   module InnerModule
       x = 2
       function f()
           global x
           println(x) # will print 2
       end
   end

   function f()
     global x
     println(x) # will print 1
   end
end

```

The following section explains Julia scoping rule in detail:  
[https://docs.julialang.org/en/v1/manual/variables-and-scoping/](https://docs.julialang.org/en/v1/manual/variables-and-scoping/)

---

<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:** [December 23, 2019, 12:06pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/5 "2019-12-23T12:06:09Z")

</div>

Incidentally, please note that the concept of “soft” and “hard” global scope is now obsolete, there is no such distinction in Julia 1.0. The manual you are using is outdated, use the link by @Sijun.

Generally, Julia underwent a lot of changes before 0.7/1.0, and a lot of material on the web is outdated.

---

<div class="post-metadata">

**Author:** ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)\
**Post date:** [December 23, 2019, 3:28pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/6 "2019-12-23T15:28:15Z")

</div>

btw: [RFC: bring back v0.6 scope rules in the REPL by JeffBezanson · Pull Request #33864 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/33864)

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [December 23, 2019, 3:54pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/7 "2019-12-23T15:54:34Z")

</div>

@Sijun , @Tamas_Papp - thank you for your advice!

@lobingera - well, I began trying to code in Julia just yesterday. If I don’t give up soon, it’s look like I’m in for quite a few surprises.

---

<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:** [December 23, 2019, 4:11pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/8 "2019-12-23T16:11:33Z")

</div>

> [@Eben60](#):
>
> it’s look like I’m in for quite a few surprises.

Mostly good ones, I can guarantee you! Have fun!

---

<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:** [December 23, 2019, 6:26pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/9 "2019-12-23T18:26:27Z")

</div>

FWIW, I think that linking discussions like this is more confusing than helpful in the “first steps” category.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 12, 2020, 12:46pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/10 "2020-01-12T12:46:48Z")

</div>

> [@Sijun](#):
>
> The scope of global variables are limited to the immediate module they belong to.  
> …  
> The following section explains Julia scoping rule in detail:  
> [https://docs.julialang.org/en/v1/manual/variables-and-scoping/](https://docs.julialang.org/en/v1/manual/variables-and-scoping/)

@Sijun , according to documentation you cited, **global** is _not_ limited to the immediate module they belong to:

> There are two main types of scopes in Julia, _global scope_ and _local scope_ . The latter can be nested.

Do I understand that correctly?

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 12, 2020, 12:50pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/11 "2020-01-12T12:50:59Z")

</div>

@Tamas_Papp 😀 Reading discussions like this was definitely confusing (as confusing as the Julia scoping rules can be) AND helpful for me.

`Loops` and `try-catch` creating a local scope may have reasons (with `try-catch-finally` creating 3 separated scopes being expecially piquant). However normally you would want to pass the results to the “outer world”.

For myself, I’d sum up the following rules to avoid scoping problems:

1. **global** is evil. Especially never call `loop` or `try-catch` constructs on the global (script) scope
2. Put everything into functions as early as possible
3. Otherwise at least put `loop` or `try-catch` into a `let` block
4. Initialize the variable to be used to return results before the `loop` or `try-catch` construct. If the variable starting value is _not_ used in the loop, initialize it with `nothing`

Like the following

```julia
let
    k = nothing
    for i in 1:2
        k = i
    end
    @show k
end

function f2()
    p = 0
    for j in 1:4
        p += j
    end
    return p
end

@show f2()

function tryit(sq)

    ll = mm = nothing
    try
        mm = 9
        ll = sqrt(sq)
    catch
        ll = sqrt(mm)
    finally
        ll += mm
    end
    return ll
end

@show tryit(10.0)
@show tryit("ten")

```

```julia
k = 2
f2() = 10
tryit(10.0) = 12.16227766016838
tryit("ten") = 12.0

```

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 12, 2020, 1:19pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/12 "2020-01-12T13:19:22Z")

</div>

As for surprises: The following code works, and I am surprised. The variable `soln` was not declared anywhere outside of the loop and to my understanding it shouldn’t be available after the loop - still it is available: I then use it as the returned value from the function` integrate_ode` .

As for the code itself: it resulted from a port of an old Python project to Julia, mainly as an excercise. I measure the execution time at the iteration # 7 to compare with Python / scipy code. BTW it is about 10 times faster (with the potential to reduce the execution time by about a second as compared with Python 😉 )

```julia
function integrate_ode(y0, x_arr, m_l_arr, p_arr, ps_arr, signum, mdl_perm_coeff, ppw_opp, iteration)
  loops = 1
  if signum < 0
    x_arr = reverse(x_arr)
  else
    if iteration == 7
      loops = 1000

    end
  end
  params = (x_arr, m_l_arr, p_arr, ps_arr, signum, mdl_perm_coeff, ppw_opp)
  xspan = (x_arr[1], x_arr[end])

  if loops > 1
    eltime = @elapsed begin
      for cnt in 1:loops
        problm = ODEProblem(own_tmq_m_w, y0, xspan, params)
        soln = solve(problm,reltol=1e-6,saveat=x_arr)
      end
      # about 3 to 4 ms per loop
    end
    @show eltime
  else
    problm = ODEProblem(own_tmq_m_w, y0, xspan, params)
    # @show y0
    soln = solve(problm,reltol=1e-6,saveat=x_arr)
  end
  if signum < 0
    return reverse(soln(x_arr).u)
  else
    return soln(x_arr).u
  end
end

```

---

<div class="post-metadata">

**Author:** ![Sijun](https://avatars.discourse-cdn.com/v4/letter/s/b2d939/32.png) [@Sijun](https://discourse.julialang.org/u/Sijun)\
**Post date:** [January 12, 2020, 2:16pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/13 "2020-01-12T14:16:15Z")

</div>

```julia
module Outer
    x = 1
    module Inner
        import ..Outer
        x = 2
        f() = println(x)
        g() = println(Outer.x)
    end
    f() = println(x)
    g() = println(Inner.x)
end

Outer.f() # 1
Outer.g() # 2
Outer.Inner.f() # 2
Outer.Inner.g() # 1

```

`x` defined in module `Outer` is not accessible to module `Inner` by the name `x` alone.  
`x` must be qualified by `Outer` (as `Outer.x`) and vise versa.

Unless qualified by appropriate module name, a variable defined in one module is not visible to other modules and (I think) can be said to be limited only to its immediate module it belongs to (so no name clash can occur).

---

<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:** [January 12, 2020, 2:27pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/14 "2020-01-12T14:27:29Z")

</div>

> [@Eben60](#):
>
> However normally you would want to pass the results to the “outer world”.

I am not so sure that I would do this via outer variables: normally I would either rethrow an error, or return a value.

---

<div class="post-metadata">

**Author:** ![Sijun](https://avatars.discourse-cdn.com/v4/letter/s/b2d939/32.png) [@Sijun](https://discourse.julialang.org/u/Sijun)\
**Post date:** [January 12, 2020, 2:52pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/15 "2020-01-12T14:52:26Z")

</div>

```julia
function foo()
    loop = 10
    if loop > 1
        for i in 1:10
            soln = 1
        end
    else
        soln = 2
    end

    println(soln)
end

```

Because of the` soln = 2` in `else` block, the above code is equivalent to this:

```julia
function foo()
    loop = 10
	local soln # soln is function-local
    if loop > 1
        for i in 1:10
            soln = 1
        end
    else
        soln = 2
    end

    println(soln)
end

```

And so the `soln` inside `for-loop` refers to `soln` local to function `foo()`.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 12, 2020, 4:45pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/16 "2020-01-12T16:45:38Z")

</div>

> [@Tamas\_Papp](#):
>
> I am not so sure that I would do this via outer variables: normally I would either rethrow an error, or return a value.

I am not sure I understood you.

```julia
try
    x = 2*2
catch e
    swear(e)
end

```

Now, should nothing “exceptional” happen, I need the value of `x`. How do I get access to it?

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 12, 2020, 4:47pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/17 "2020-01-12T16:47:13Z")

</div>

@Sijun thank you for your explanation on modules scope

---

<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:** [January 12, 2020, 4:52pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/18 "2020-01-12T16:52:40Z")

</div>

If no exceptions are thrown, the value of the above expressions is just `4`. Just use it directly. No need to assign it to `x`.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [January 12, 2020, 5:03pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/19 "2020-01-12T17:03:33Z")

</div>

> [@Tamas\_Papp](#):
>
> Just use it directly.

Thank you! So the code would be (yes, it works!)

```julia
x = try
    2*2
catch e
    swear(e)
end

@show x # x = 4

```

The same is valid for `let`. The same is NOT valid for loops 🙄

---

<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:** [January 12, 2020, 5:11pm UTC](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617/20 "2020-01-12T17:11:18Z")

</div>

`for` loops have value `nothing`, so yes, use them for side effects.

[Next page](https://discourse.julialang.org/t/scoping-rules-for-try-catch-finally/32617.md?page=2)
