# Confused by behaviour of nested functions

**URL:** <https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576>\
**Category:** New to Julia\
**Created:** [February 8, 2019, 10:52am UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576 "2019-02-08T10:52:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![sbarthelme](https://avatars.discourse-cdn.com/v4/letter/s/839c29/32.png) [@sbarthelme](https://discourse.julialang.org/u/sbarthelme)\
**Post date:** [February 8, 2019, 10:52am UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/1 "2019-02-08T10:52:35Z")

</div>

Dear Julia users,

I must confess to finding the following behaviour extremely puzzling - I suspect it’s related to scoping, but I can’t make heads or tails of it. Here’s a simple function featuring nested functions:

```julia
function test1(arg)
    if (arg==1)
        f(x) = 3*x
        f(1)
    else
        a = 5
        f(x) = a*x
        f(2)
    end
end

```

Now calling test1(1) gives me:  
ERROR: UndefVarError: a not defined

and test(2) gives me  
ERROR: UndefVarError: f not defined

Executing the above code directly in the REPL works fine, though, ie:

```julia
arg = 1
if (arg==1)
    f(x) = 3*x
    f(1)
else
    a = 5
    f(x) = a*x
    f(2)
end

```

Here’s a variant that fails in a different manner:

```julia
function test2(arg)
    f(x) = x
    if (arg==1)
        f(x) = 3*x
        f(1)
    else
        a = 5
        f(x) = a*x
        f(2)
    end
end

```

Now test2(1) still fails with the same error but test2(2) works.

Finally, this variant works fine:

```julia
function test3(arg)
    if (arg==1)
        f = (x) -> 3*x
        f(1)
    else
        a = 3
        f = (x) -> a*x
        f(2)
    end
end

```

This on julia 1.0.3. What gives?

Thanks!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 8, 2019, 10:55am UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/2 "2019-02-08T10:55:28Z")

</div>

Don’t define functions conditionally inside other functions: [disallow methods of local functions in different blocks · Issue #15602 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15602).

---

<div class="post-metadata">

**Author:** ![sbarthelme](https://avatars.discourse-cdn.com/v4/letter/s/839c29/32.png) [@sbarthelme](https://discourse.julialang.org/u/sbarthelme)\
**Post date:** [February 8, 2019, 11:16am UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/3 "2019-02-08T11:16:39Z")

</div>

All right, thanks!

---

<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:** [February 8, 2019, 1:01pm UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/4 "2019-02-08T13:01:53Z")

</div>

Just in case it wasn’t clear, using anonymous functions (as your test3 does) is the recommended way to avoid this problem. There is also no performance penalty for anonymous functions in Julia, so it should work quite well.

---

<div class="post-metadata">

**Author:** ![sbarthelme](https://avatars.discourse-cdn.com/v4/letter/s/839c29/32.png) [@sbarthelme](https://discourse.julialang.org/u/sbarthelme)\
**Post date:** [February 8, 2019, 4:52pm UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/5 "2019-02-08T16:52:46Z")

</div>

Just curious, but in this case why not simply forbid non-anonymous nested functions? The current behaviour is super confusing for beginners, especially from lisp-y languages like R.

---

<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:** [February 8, 2019, 6:21pm UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/6 "2019-02-08T18:21:47Z")

</div>

Good question. The problem only occurs when you have _conditionally defined_ nested functions, like this:

```julia
function foo()
  # which definition of f() will occur? who knows?
  if rand() < 0.5
    f(x) = x + 1
  else
    f(x) = x + 2
  end
  f(1)
end

```

If the definition isn’t inside a conditional (like the `if` block above), then everything works:

```julia
function foo()
  # this if fine
  f(x) = x + 1
  f(1)
end

```

But I totally agree that the former behavior is confusing. I would support making the former an error (or, of course, making it actually work as expected). Such a change would technically be breaking, though, so it might not be possible until Julia 2.0. I’d have to leave that question to the core devs.

---

<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:** [February 8, 2019, 8:59pm UTC](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576/7 "2019-02-08T20:59:06Z")

</div>

Yes, this is a long-standing bug I would like to fix. It arises from a combination of

1. Functions can have multiple methods
2. The syntax for adding a method and creating a new function is the same
3. We insist that the set of methods in a function only change at the top level

What we don’t want, for example, is for `f` to have different methods for different argument values to `test1`. Given that, it’s not clear what the code should mean and it should probably be an error, but it’s not clear what the rules should be exactly.

We don’t want to entirely forbid non-anonymous nested functions, since (other than this issue) it’s fairly easy to support nested functions with multiple methods.
