All ways to define functions in Julia?

I tried to list all the ways one can define functions in Julia. Some are practical, some are silly but collecting them all is fun.

Planning to make a video for fun exploring this.


function name(a, b)
    a + b
end

name(a,b) = a + b

if false
    name = (a,b) -> a+b
end

name2 = (a,b) -> a+b

name3 = function(a, b)
    a+b
end

macro defining_function(fnname)
    :(
        function $fnname(a, b)
            a+b
        end
    )
end

@defining_function name4

function fn_generator()
    function (a, b)
        a*b
    end
end

name5 = fn_generator()

function fn_generator2()
    function name(a, b)
        a*b
    end
end

# what would happen here?
fn_generator2()

edit

Thanks to @thofma for a+b=a*b

I just thought of LambdaFn.jl GitHub - haberdashPI/LambdaFn.jl: Alternative, underscore syntax for anonymous functions in Julia which allows

@lf _+_

12 Likes

a * b = a + b

18 Likes

I am shocked and horrified. :joy:

7 Likes

Mind blown!

1 Like
name3 = function(a, b)
    a+b
end

This one is also surprising to me. Is that described somewhere in the manual? It’s rather reminiscent of the way you define functions in R…

1 Like

Yeah. It’s got interesting properties though.

the RHS is just another syntax to define an anonymous function so it’s the same as

name3 = (a,b) -> a+b

But typeof(name3) is NOT name! It’s the “name” given to the anonymous function.

Interestingly, @edit name3(1,2) can stil find it

1 Like

This is very interesting as well

function (x::Int)(y)

    x+y

end

x = 2

x(2)

what is this called? function (x::Int)(y)

Functors, typically.

https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects

4 Likes

Can we change that? afaik it’s only C++ that calls those “functors” and everywhere else “functors” are a different thing. “Callables” is a good and widely used name.

6 Likes
struct Name <: Function end

(::Name)(a,b) = a+b

const name = Name()
5 Likes

yeah, i got a pure math degree so functor is a totally different thing to me I think.

4 Likes

What do you mean by that example? If you enter it at the Julia prompt, then name is not defined afterwards.

Just the content within false

What about this one?

function fn_generator()
    if true
        f() = 0
    else
        f(x, y) = x+y
    end
end

name = fn_generator()

name(1,2)   # 3

cool

This is the same as

function fn_generator()
        f(x, y) = x+y
end

since true branch is ignored. And original version should produce warning in 1.6 or 1.7

This is surprising. What is happening here?

The last definition of f is used. Some may see this as a bug. To avoid this “behaviour” use anonymous functions instead.

julia> function fn_generator()
           if true
               f = () -> 0
           else
               f = (x, y) -> x+y
           end
       end
fn_generator (generic function with 1 method)

julia> name = fn_generator()
#10 (generic function with 1 method)

julia> name()
0

See disallow methods of local functions in different blocks · Issue #15602 · JuliaLang/julia · GitHub and Defining a function inside if...else..end NOT as expected?.

5 Likes

I don’t see a warning for either version. Can you demonstrate this?

UPDATE:

Ah, I see, the function signature must be the same (it isn’t in the example above):

julia> function fn_generator()
           if true
               f() = 0
           else
               f() = 2
           end
       end
WARNING: Method definition f() in module Main at REPL[1]:3 overwritten at REPL[1]:5.
fn_generator (generic function with 1 method)
3 Likes