# Function closures and ifelse with unexpected behaviour

**URL:** <https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694>\
**Category:** New to Julia\
**Tags:** closure\
**Created:** [August 28, 2020, 2:32pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694 "2020-08-28T14:32:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![carlomontec](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carlomontec/32/2011_2.png) [@carlomontec](https://discourse.julialang.org/u/carlomontec)\
**Post date:** [August 28, 2020, 2:32pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/1 "2020-08-28T14:32:34Z")

</div>

Hello,

I am quite confused with the following behavior of this function:

```julia
function switchcase(i, str)

    case = str
    if uppercase(case) == "A"
    	@info "set case A"
       showcase(i) = @printf("case A number %i", i)
    elseif uppercase(case) == "B"
    	@info "set case B"
       showcase(i) = @printf("case B number %i and some more parameters %i", i,8)
    else
        @error("no case $case")
    end
    showcase(i)
end

```

where outputs are as following:

```julia
julia> switchcase(2, "A")
[ Info: set case A
case B number 2 and some more parameters 8
julia> switchcase(2, "B")
[ Info: set case B
ERROR: UndefVarError: showcase not defined
Stacktrace:
 [1] switchcase(::Int64, ::String) at ./REPL[224]:13
 [2] top-level scope at REPL[226]:1

```

My intention is to use closures to define different perturbation sources in a bigger simulation code. Given an inputs file, the correct perturbation model is called.

Is it perhaps related to this post? [Surprising capture boxing behavior in closure](https://discourse.julialang.org/t/surprising-capture-boxing-behavior-in-closure/20254)

I would be thankful for any hint to understand this outcome.

---

<div class="post-metadata">

**Author:** ![jmert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmert/32/3161_2.png) [@jmert](https://discourse.julialang.org/u/jmert)\
**Post date:** [August 28, 2020, 2:47pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/2 "2020-08-28T14:47:52Z")

</div>

See [this previous question](https://discourse.julialang.org/t/confused-by-behaviour-of-nested-functions/20576) which boils down the same problem.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 28, 2020, 3:00pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/3 "2020-08-28T15:00:35Z")

</div>

I wandered if this alternative works, in which the functions are defined before and the conditional only assigns a new name, but I get a segmentation fault error. Any comment on that?

```julia
julia> using Printf

julia> showcaseA(i) = @printf("case A number %i", i)
showcaseA (generic function with 1 method)

julia> showcaseB(i) = @printf("case B number %i and some more parameters %i", i,8)
showcaseB (generic function with 1 method)

julia> function switchcase(i, str)
           case = str
           if uppercase(case) == "A"
                   @info "set case A"
              showcase = showcaseA
           elseif uppercase(case) == "B"
                   @info "set case B"
              showcase = showcaseB
           else
               @error("no case $case")
           end
           showcase(i)
       end
switchcase (generic function with 1 method)

julia> switchcase(2, "A")

signal (11): Segmentation fault
in expression starting at REPL[6]:1
operator() at /buildworker/worker/package_linux64/build/src/codegen.cpp:6101 [inlined]
emit_function at /buildworker/worker/package_linux64/build/src/codegen.cpp:6211
jl_emit_code at /buildworker/worker/package_linux64/build/src/codegen.cpp:6431
jl_emit_codeinst at /buildworker/worker/package_linux64/build/src/codegen.cpp:6465
_jl_compile_codeinst at /buildworker/worker/package_linux64/build/src/jitlayers.cpp:97
jl_generate_fptr at /buildworker/worker/package_linux64/build/src/jitlayers.cpp:302
jl_compile_method_internal at /buildworker/worker/package_linux64/build/src/gf.c:1964

```

Yet, a simpler version of this trial works:

```julia
ulia> f(i) = i + 1
f (generic function with 1 method)

julia> g(i) = i + 2
g (generic function with 1 method)

julia> function h(i)
         if i == 1
           s = f
         else
           s = g
         end
         s(i)
       end
h (generic function with 1 method)

julia> h(1)
2

julia> h(2)
4

```

---

<div class="post-metadata">

**Author:** ![jmert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmert/32/3161_2.png) [@jmert](https://discourse.julialang.org/u/jmert)\
**Post date:** [August 28, 2020, 3:01pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/4 "2020-08-28T15:01:39Z")

</div>

I was just poking at that — if you remove the `@info` and `@error` lines, the segfault goes away.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 28, 2020, 3:07pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/5 "2020-08-28T15:07:44Z")

</div>

Actually removing only the `@` from `@error` solves that:

```julia
julia> showcaseA(i) = @printf("case A number %i", i)
showcaseA (generic function with 1 method)

julia> showcaseB(i) = @printf("case B number %i and some more parameters %i", i,8)
showcaseB (generic function with 1 method)

julia> switchcase(2, "A")^C

julia> function switchcase(i, str)
                  case = str
                  if uppercase(case) == "A"
                          @info "set case A"
                     showcase = showcaseA
                  elseif uppercase(case) == "B"
                          @info "set case B"
                     showcase = showcaseB
                  else
                      error("no case $case")
                  end
                  showcase(i)
              end
switchcase (generic function with 1 method)

julia> switchcase(2, "B")
[ Info: set case B
case B number 2 and some more parameters 8
julia> switchcase(2, "A")
[ Info: set case A
case A number 2
julia> switchcase(2, "C")
ERROR: no case C

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 28, 2020, 3:18pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/6 "2020-08-28T15:18:03Z")

</div>

The `@error` macro makes the error be non-fatal, and the function continues to evaluate the `showcase` function, which will not be defined in that case.

If we add any assignment for showcase after the error, the segmentation fault disappears, and one gets a sensible error message:

```julia
                  else
                      @error("no case $case")
                      showcase = nothing          
                  end

```

```julia
julia> switchcase(2, "C")
┌ Error: no case C
└ @ Main REPL[7]:8
ERROR: MethodError: objects of type Nothing are not callable
Stacktrace:
 [1] switchcase(::Int64, ::String) at ./REPL[7]:11
 [2] top-level scope at REPL[10]:1

```

The correct error message should be, without the definition of `showcase` after the error:

```julia
julia> switchcase(2, "C")
┌ Error: no case C
└ @ Main REPL[11]:6
ERROR: UndefVarError: showcase not defined
Stacktrace:
 [1] switchcase(::Int64, ::String) at ./REPL[11]:8
 [2] top-level scope at REPL[12]:1

```

Which is actually what we get if removing, for example, the `elseif ... ` from the code. I think that that segmentation fault is a bug somewhere:

```julia
julia> function switchcase(i, str)
                  case = str
                  if uppercase(case) == "A"
                     showcase = showcaseA
                  else
                      @error("no case $case")
                  end
                  showcase(i)
              end
switchcase (generic function with 1 method)

julia> switchcase(2, "C")
┌ Error: no case C
└ @ Main REPL[11]:6
ERROR: UndefVarError: showcase not defined
Stacktrace:
 [1] switchcase(::Int64, ::String) at ./REPL[11]:8
 [2] top-level scope at REPL[12]:1

```

---

<div class="post-metadata">

**Author:** ![jmert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmert/32/3161_2.png) [@jmert](https://discourse.julialang.org/u/jmert)\
**Post date:** [August 28, 2020, 3:20pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/7 "2020-08-28T15:20:46Z")

</div>

I’ve filed an [issue with Julia](https://github.com/JuliaLang/julia/issues/37265) that includes the fancy-new `--bug-report=rr` tracing feature.

---

<div class="post-metadata">

**Author:** ![jmert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmert/32/3161_2.png) [@jmert](https://discourse.julialang.org/u/jmert)\
**Post date:** [August 28, 2020, 3:31pm UTC](https://discourse.julialang.org/t/function-closures-and-ifelse-with-unexpected-behaviour/45694/8 "2020-08-28T15:31:52Z")

</div>

> [@lmiq](#):
>
> If we add any assignment for showcase after the error, the segmentation fault disappears, and one gets a sensible error message:  
> …  
> The correct error message should be [an `UndefVarError`], without the definition of `showcase` after the error:

Yeah, you’re completely right. Also, trying an interactive `@run switchcase(2, "C")` with `Debugger.jl` stops the segfault, but it’s still stalling within the logging (in a way I don’t completely understand since it _seems_ to be during the `elseif` branch and not the `else` branch as I expected… But that could just be another symptom of something malformed.)
