Nested function logic

Suppose I define the function f(x) as follows:

function f(x)
       if true
           g(x) = 2x
       else
           g(x) = 3x
       end
       g(x)
end

To me it was very surprising that calling f(2) returns 6 instead of 2. Can someone explain this behavior?

Try

function f(x)
    if true
        g = x -> 2x
    else
        g = x -> 3x
    end 
    g(x)
end 

My understanding is that doing either function f end or f(args...) = #code creates a function f in the namespace of the current module. However anonymous functions (“lambdas”) are not like this.

Note that you could do

@static if true
    g(x) = 2x
else
    g(x) = 3x
end

in the global scope of the module and it should work fine (in fact, you probably don’t even need the @static if you do it in global scope).

Ideally I think your code should throw a warning.

Related:

https://github.com/JuliaLang/julia/issues/15602

There should really be some documentation about this. It was totally unexpected until it was explained to me.

It doesn’t throw a warning when I execute it at the REPL. Inside a script I do get warnings.

That makes sense. I know that the REPL does various things to cut down on compile time (or perhaps just to silence warnings?), but I don’t know the details.

Does this allow you to do multi-method functions?

Yes it does. Although I’m not 100% sure I understand why this works and my original code doesn’t.