Same code in if and else blocks, get UndefVarError only on else condition

scope

#1

Suppose I have a function with 2 arguments, and I want to make a new function with one of the arguments fixed to a value, depending on some condition. For example:

fun(x,a) = a*x
function foo(flag::Bool)
   if flag
       bar(x) = fun(x,2)
   else
       bar(x) = fun(x,2)
   end
   return bar
end

In this example the value of a is fixed to 2 on both branches, just for illustration.
If I run this code in a script, foo(true) returns the desired function, but foo(false) gives

ERROR: UndefVarError: bar not defined
Stacktrace:
 [1] foo(::Bool) at .\none:7
 [2] eval(::Module, ::Any) at .\boot.jl:235

I realize now at least a couple of different ways to re-write foo so that it works, but my question is why does the above version not work when control flows down the else branch? I think I can learn something by understanding this, but I can’t make sense of it in terms of my understanding of scoping rules.

Thank you (I’m using Julia 0.6.2, BTW)


#2

You cannot define a function conditionally in this way because the function method table needs to be constructed at the top level. https://github.com/JuliaLang/julia/issues/15602 has an explanation and some discussion of workarounds. For your purpose you should probably make bar an anonymous function like this:

bar = x -> fun(x, 2)

#3

Thank you and sorry for duplicating the issue you linked. If this type of conditional function definition is not allowed in Julia, it should probably produce a (more informative) error in both the true and false cases. Since that issue is still open, I assume better handling of this problem (and some corresponding documentation) will appear in due course.


#4

Yes, though the quickest way to make the documentation appear is probably to add it yourself :slight_smile: It may be worth adding a note in the Conditional Evaluation or Functions section of the manual until the root problem is fixed or a better error/warning is added.