Different behaviors


#1

Consider the following code:

x = 0
y = 1
if y>0
f(x) = x
else
f(x) = 10000
end
y = (f(x))^2
println(y)

Running this code simply prints 0. No surprises here. Now, define the function myfun as follows:

function myfun(x, y)
if y>0
f(x) = x
else
f(x) = 10000
end
y = (f(x))^2
return y
end

Then, I expected that myfun(0,1) would return the same value as the above code. But actually it does not but it returns 100000000.

What am I not understanding here? Please help…


#2

Not allowed (https://github.com/JuliaLang/julia/issues/17782 ) use anonymous functions


#3

To expand briefly on @pkofod’s response, defining named functions within a function is not supported. To achieve the desired behavior, you can to use anonymous functions. So your second example should be written instead as

function myfun(x, y)
    if y > 0
        f = x -> x
    else
        f = x -> 10000
    end
    y = f(x)^2
    return y
end

As I understand it, allowing f to be a “regular” function here is problematic because it may have different methods depending on the code path, and rebuilding its method list on each call is slow.

The simpler, more Julian approach here would be to define f outside of myfun:

f(x, y) = y > 0 ? x : 10000
myfun(x, y) = f(x, y)^2

#4

They are I thought. As long as they are not conditionally defined like in this example?

julia> f(y) = (g(x) = x + y)
f (generic function with 2 methods)

julia> g5 = f(5)
(::g) (generic function with 1 method)

julia> g5(3)
8

I don’t agree. Defining closures inside functions is very “Julian” in my view.


#5

Defining “named” function in local scope/as closure is fully supported, the difference is the function type.

In the same scope, all functions definitions of the same name are of the same type. So

function f()
    ...
    g(...) = ...
    ...
    g(...) = ...
end

Will create a type with two methods. The type and methods definitions are generated at compile (lowering) time and be define before f is called. (Though calling them with the wrong signature might cause undefined variable error)

Anonymous functions don’t have a name (because, well, they are anonymous…) so they each have their own types.


#6

Oops. I accidentally submitted a reply before it was completed. I will try to do it again here.

It is good to define

f(x,y) = y>0 ? x: 10000
myfun(x,y) = f(x,y)^2

when there is only one condition. Suppose that I want to use

if y<0
f = x -> x
elseif 0<= y < 1
f = x -> x^2
else
f = x -> 10000
end

In this case I guess I can simply use

f(x,y) = x * (y<0) + (x^2) * (0<=y<1) + 10000 * (y>=1)

Do you have any comments about this approach?

Thank you.