In Julia, I know of three ways to define a named multiline function:
1.
function f(x, y)
...
end
2.
f = function(x, y)
...
end
3.
f(x, y) = begin
...
end
They all seem to produce the same outcome.
Is there any difference? Which one should be used and why?
Every function in Julia is a generic function. A generic function is conceptually a single function, but consists of many definitions, or methods. The methods of a generic function are stored in a method table. Method tables (type MethodTable ) are associated with TypeName s.
A return type can be specified in the function declaration using the :: operator. This converts the return value to the specified type. This function will always return an Int8 regardless of the types of x and y .
Variables in Julia can be declared by just writing their name. There's no need to define a datatype with it. Initializing variables can be done at the time of declaring variables. This can be done by simply assigning a value to the named variable.
It is a purely syntactical transformation. if you will, i.e. the do block defines an anonymous function that is passed as the first argument. For this to work it is, of course, required that there exist a method of func that has a matching signature, for example func(f::Function, ...)
1 and 3 are functionally identical, but 1 is preferred stylistically. The "short form function declaration" f(x,y) = …
is typically used (and encouraged) for one-line definitions — that is, without a begin
block.
2 is different. It's creating an anonymous function, and then assigning it to f
. Note that unlike the bindings created by 1 and 3, you can actually reassign f
to completely different things. This means that Julia cannot assume that f
will always call that function, which means that it cannot do any of its normal optimizations. Now, if you used const f = function(x, y) …
, then f
is a constant binding and it should behave similarly to the other declarations. But note that f
is still just a binding to an anonymous function — the function itself doesn't know what its name is! So it'll print as #1 (generic function with 1 method)
instead of f (generic function with 1 method)
.
See https://docs.julialang.org/en/stable/manual/functions/ for more details.
Definitions 1 and 3 are equivalent (the difference is only style, option 1 is usually preferred). They define function f
for which you can implement multiple methods (https://docs.julialang.org/en/v1/manual/methods/).
Definition 2 creates an anonymous function and assigns it to a global variable f
. I would not encourage it in general.
If you would call such a function inside other function using name f
the result would not be type stable (variable f
from global scope would have to be resolved). Anonymous functions are usually used in situations where the name is not important.
Actually there are two other ways to define multiple line anonymous function (again - I do not encourage it but show it for completeness):
f = x -> begin
...
end
and
f = identity() do x
...
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With