Why does Julia have multiple ways to define functions?

Me neither. The (::typeof(h)) thing is actually very logical if you look up the couple sections on functors and realize that a function is just an instance of a singleton type, that’s not the part that I complain about.

I also prefer if there was only 1 way to do things, but if you try to stick to 1 form instead of the typical usages, you hit parser issues. Let’s take the 4 forms: named function, anonymous function, named =, and anonymous -> (the latter two take single expressions, not single lines):

return type issue for anonymous `function` and `->` forms
julia> function f(x::Int)::Int 0 end
f (generic function with 1 method)

julia> function (x::Int)::Int 0 end # comma or more arguments does not help
ERROR: syntax: ambiguous signature in function definition. Try adding a comma if this is a 1-argument anonymous function...

julia> f(x::Int)::Int = 0
f (generic function with 1 method)

julia> ((x::Int)::Int) -> 0 # even parentheses doesn't help
ERROR: syntax: "x::Int" is not a valid function argument name around...
return type and `where` clause issue for anonymous `function`, `=`, and `->` forms
julia> function f(x::T)::Int where T 0 end
f (generic function with 1 method)

julia> function (x::T)::Int where T 0 end # comma or more arguments does not help
ERROR: syntax: ambiguous signature in function definition. Try adding a comma if this is a 1-argument anonymous function...

julia> f(x::T)::Int where T = 0
ERROR: UndefVarError: T not defined

julia> (f(x::T)::Int) where T = 0 # need parentheses to work
f (generic function with 1 method)

julia> ((x::T)::Int) where T -> 0 # parentheses doesn't help
ERROR: syntax: invalid variable expression in "where" around...
single-line parentheses, brackets, or braces expression issue for named and anonymous `function` forms
julia> function f(x) (x,) end
ERROR: syntax: space before "(" not allowed in "f(x) (" at...

julia> function f(x)(x,) end # ^it thought (x,) was the arguments expression
ERROR: syntax: invalid function name "f(x)" around

julia> function f(x); (x,) end # need new line or ; to work
f (generic function with 1 method)

julia> function (x); (x,) end # need new line or ; to work
#1 (generic function with 1 method)

julia> f(x) = (x,)
f (generic function with 1 method)

julia> (x) -> (x,)
#3 (generic function with 1 method)

I think it should be possible to patch these issues, since we can identify the proper rules: {optional name or (var::type) parentheses}{no space here!!}{arguments parentheses}::{optional return type} where {optional arguments’ type parameters brace}{function body} {end}. But patching the parser is probably really hard. I think if somebody (me) would like to use 1 form for everything, it’d be a patched function block.

2 Likes