julia function declaration style

2020-04-07 05:01发布

问题:

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?

回答1:

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.



回答2:

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/latest/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