# Return a function defined in a function

**URL:** <https://discourse.julialang.org/t/return-a-function-defined-in-a-function/21849>\
**Category:** New to Julia\
**Created:** [March 14, 2019, 2:33am UTC](https://discourse.julialang.org/t/return-a-function-defined-in-a-function/21849 "2019-03-14T02:33:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Adriel](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@Adriel](https://discourse.julialang.org/u/Adriel)\
**Post date:** [March 14, 2019, 2:33am UTC](https://discourse.julialang.org/t/return-a-function-defined-in-a-function/21849/1 "2019-03-14T02:33:31Z")

</div>

Is anyone able to explain this behaviour?

```julia
function fx(n)
    if n == 1
        f(x) = 2x
    else
        f(x) = 3x
    end
    f
end

```

Seems simple enough, but…

```julia
julia> fx(1)(1) # expecting 2
3

julia> fx(2)(1) # expecting 3
ERROR: UndefVarError: f not defined
Stacktrace:
 [1] fx(::Int64) at .\REPL[1]:7
 [2] top-level scope at none:0

```

I tried a few things like declaring `f` as `global`, but I’m still stumped. A pointer to the relevant docs would be really appreciated!

---

<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:** [March 14, 2019, 2:53am UTC](https://discourse.julialang.org/t/return-a-function-defined-in-a-function/21849/2 "2019-03-14T02:53:37Z")

</div>

It’s an unfortunate and long-standing bug. See: [Confused by behaviour of nested functions](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576) for more discussion.

Fortunately, it’s easy to avoid by defining an anonymous function instead:

```julia
function fx(n)
  if n == 1
    f = x -> 2x
  else
    f = x -> 3x
  end
  f
end

```

---

<div class="post-metadata">

**Author:** ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)\
**Post date:** [March 14, 2019, 3:16am UTC](https://discourse.julialang.org/t/return-a-function-defined-in-a-function/21849/3 "2019-03-14T03:16:04Z")

</div>

if the function if not complicated, you can do the conditional first and define a general function:

```julia
function fx(n)
    if n == 1
        a = 2
    else
        a = 3
    end
    f(x) = a*x
    return f
end

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 14, 2019, 6:47am UTC](https://discourse.julialang.org/t/return-a-function-defined-in-a-function/21849/4 "2019-03-14T06:47:09Z")

</div>

> [@longemen3000](#):
>
> if the function if not complicated, you can do the conditional first and define a general function

This particular way of doing it is not a good idea since it generates type unstable code:

```julia
julia> @code_typed fx(1)(1)
CodeInfo(
1 ─ %1 = (Core.getfield)(#self#, :a)::Box
│ %2 = (Core.isdefined)(%1, :contents)::Bool
└── goto #3 if not %2
2 ─ goto #4
3 ─ $(Expr(:throw_undef_if_not, :a, false))::Any
4 ┄ %6 = (Core.getfield)(%1, :contents)::Any
│ %7 = (%6 * x)::Any
└── return %7
) => Any

```

Compare to @rdeits suggestion:

```julia
julia> @code_typed fx(1)(1)
CodeInfo(
1 ─ %1 = (Base.mul_int)(2, x)::Int64
└── return %1
) => Int64

```

However, that code may suffer from similar issues if either the input `n` is not compile time known:

```julia
julia> fxwrapped(x) = fx(x)(x);

julia> fxwrapped(2)
6

julia> @code_typed fxwrapped(3)
CodeInfo(
1 ─ %1 = (x === 1)::Bool
└── goto #3 if not %1
2 ─ %3 = %new(Main.:(##133#135))::##133#135
└── goto #4
3 ─ %5 = %new(Main.:(##134#136))::##134#136
4 ┄ %6 = φ (#2 => %3, #3 => %5)::Union{##133#135, ##134#136}
└── goto #5
5 ─ %8 = (%6)(x)::Any
└── return %8
) => Any

```

Or if `f` is subsequently used:

```julia
function fx2(n)
  if n == 1
    f = x -> 2x
  else
    f = x -> 3x
  end
  x -> f(2x)
end

```

Problem:

```julia
julia> fx2(1)(1)
4

julia> @code_typed fx2(1)(1)
CodeInfo(
1 ─ %1 = (Core.getfield)(#self#, :f)::Box
│ %2 = (Core.isdefined)(%1, :contents)::Bool
└── goto #3 if not %2
2 ─ goto #4
3 ─ $(Expr(:throw_undef_if_not, :f, false))::Any
4 ┄ %6 = (Core.getfield)(%1, :contents)::Any
│ %7 = (Base.mul_int)(2, x)::Int64
│ %8 = (%6)(%7)::Any
└── return %8
) => Any

```

A workaround for both issues is to have a single definition of `f`, and also ensure that there’s no uncertainty of existence of variables:

```julia
function fx3(n)
    a = ifelse(n == 1, 2, 3)
    f(x) = a*x
    return x -> f(2x)
end

fx3wrapped(x) = fx3(x)(x)

```

Type stability ensues:

```julia
julia> @code_typed fx3(2)(1)
CodeInfo(
1 ─ %1 = (Core.getfield)(#self#, :f)::#f#160{Int64}
│ %2 = (Base.mul_int)(2, x)::Int64
│ %3 = (Core.getfield)(%1, :a)::Int64
│ %4 = (Base.mul_int)(%3, %2)::Int64
└── return %4
) => Int64

julia> @code_typed fx3wrapped(2)
CodeInfo(
1 ─ %1 = (x === 1)::Bool
│ %2 = (Main.ifelse)(%1, 2, 3)::Int64
│ %3 = (Base.mul_int)(2, x)::Int64
│ %4 = (Base.mul_int)(%2, %3)::Int64
└── return %4
) => Int64

```
