I am quite confused with the following behavior of this function:
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> 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.
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> 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:
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
Actually removing only the @ from @error solves that:
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
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:
else
@error("no case $case")
showcase = nothing
end
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> 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> 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
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.)