【发布时间】:2018-01-27 23:17:24
【问题描述】:
在 Julia 中,我知道定义命名多行函数的三种方法:
1.
function f(x, y)
...
end
2.
f = function(x, y)
...
end
3.
f(x, y) = begin
...
end
它们似乎都产生了相同的结果。
有什么区别吗?应该使用哪一个?为什么?
【问题讨论】:
在 Julia 中,我知道定义命名多行函数的三种方法:
1.
function f(x, y)
...
end
2.
f = function(x, y)
...
end
3.
f(x, y) = begin
...
end
它们似乎都产生了相同的结果。
有什么区别吗?应该使用哪一个?为什么?
【问题讨论】:
1 和 3 在功能上相同,但在风格上首选 1。 “短格式函数声明”f(x,y) = … 通常用于(并鼓励)单行定义——也就是说,没有 begin 块。
2 不同。它正在创建一个匿名 函数,然后将其分配给f。请注意,与 1 和 3 创建的绑定不同,您实际上可以重新分配 f 到完全不同的东西。这意味着 Julia 不能假设 f 将始终调用该函数,这意味着它无法进行任何正常的优化。现在,如果您使用了const f = function(x, y) …,那么f 是一个常量绑定,它的行为应该与其他声明类似。但请注意,f 仍然只是一个匿名函数的绑定——函数本身并不知道它的名字是什么!所以它将打印为#1 (generic function with 1 method) 而不是f (generic function with 1 method)。
更多详情请见https://docs.julialang.org/en/stable/manual/functions/。
【讨论】:
定义 1 和 3 是等价的(区别仅在于样式,通常首选选项 1)。他们定义了函数f,您可以为其实现多种方法(https://docs.julialang.org/en/v1/manual/methods/)。
定义 2 创建一个匿名函数并将其分配给全局变量f。我一般不会鼓励它。
如果您使用名称 f 在其他函数中调用此类函数,则结果将不是稳定类型(必须解析来自全局范围的变量 f)。匿名函数通常用于名称不重要的情况。
实际上还有另外两种定义多行匿名函数的方法(同样——我不鼓励这样做,但为了完整起见):
f = x -> begin
...
end
和
f = identity() do x
...
end
【讨论】:
import Base: +; s1::String + s2::String = s1 * s2; "foo" + "bar" # returns "foobar"
-> begin,我希望我永远不会看到identity() do x。