# Functions as fields of mutable struct in if-elseif environment

Hi,
so I’m trying to do define functions as fields of a mutable struct based on input parameters. The general structure of which has the following form

``````module TestModule
mutable struct TestStruct
F
function TestStruct(args...)
f(x) = x;
if length(args)==0
println("0 args")
f(x)  = x
println("The value of f(x)=x at x=1.0 is \$(f(1.0))")
return new(f)
elseif length(args)>0
println("at least 1 arg")
f(x) = -x;
println("The value of f(x)=-x at x=1.0 is \$(f(1.0))")
return new(f)
end
end
end
end
``````

which seems to produce the wrong value for f(x), in the sense that

``````c=MyModule.MyStruct();
``````

produces

``````0 args
The value of f(x)=x at x=1.0 is -1.0

``````

which is wrong, and, e.g.

``````c=MyModule.MyStruct(1);
``````

gives

``````at least 1 arg
The value of f(x)=-x at x=1.0 is -1.0
``````

However, if I remove all occurrences of elseif , I get a correct assignment of c.F function to f(x) = x, i.e.

``````module TestModule
mutable struct TestStruct
F
function TestStruct(args...)
f(x) = x;
if length(args)==0
println("0 args")
f(x)  = x
println("The value of f(x)=x at x=1.0 is \$(f(1.0))")
return new(f)
end
end
end
end
``````

Is this behavior intentional? am I’m doing weird design flops?
how do I get the field F of a mutable struct to be assigned the correct function in the ifelse environment?
Thanks!

Use anonymous functions for `f` (`f = x -> x` and `f = x -> -x`), see e.g. Defining a function inside if...else..end NOT as expected?. There is also an issue about this that I can’t find now.

2 Likes

Yeah, this is an (in my opinion, unfortunate) consequence of Julia’s design. It’s not necessary to have a `struct` definition involved to see the issue, you can simply do:

``````julia> function foo()
f() = 0
if true
f() = 1
else
f() = 2
end
return f
end
foo (generic function with 1 method)

julia> f = foo()
f (generic function with 1 method)

julia> f()
2  # nooooooooo
``````

Basically, inside a function, all of those `f() = whatever` definitions get compiled before a particular branch of the `if-else` statement is chosen, and they all modify the definition of the same function `f()`. `f()` can only do one thing, so it ends up doing whatever the last definition was, even if that branch of the `if-else` will not be chosen at run-time.

Fortunately, the fix is very simple: if you use anonymous functions, you can make sure that each branch of the `if-else` returns a different, correct, anonymous function:

``````julia> function foo()
if true
f = () -> 1
else
f = () -> 2
end
end
foo (generic function with 1 method)

julia> f = foo()
#7 (generic function with 1 method)

julia> f()
1  # what you expected
``````
10 Likes