我试图理解一段相对简单的代码,但我不太能理解发生了什么(我是来自 Python/Matlab 背景的 Julia 新手)。
function myfunc(number::Integer)
double() = 2*number
square() = number^2
return _ -> (number, double, square)
end
我明白
myfunc
正在返回一个不关心传递给它的值的匿名函数。所以这些案例对我来说很有意义:julia> n4 = myfunc(4)
#9 (generic function with 1 method)
julia> n4(50)
(4, var"#double#10"{Int64}(4), var"#square#11"{Int64}(4))
在第一行
n4
指匿名函数本身,而在第二个匿名函数中调用参数 50
并执行它应该做的:丢弃 50 并返回包含它定义的数据的元组。我不明白的是我如何能够做到:
julia> n4.square
(::var"#square#11"{Int64}) (generic function with 1 method)
julia> n4.square()
16
事实
n4
这是指匿名函数有子对象n4.number
, n4.double
, n4.square
对我来说是个惊喜。怎么样n4
表现得好像它是一个结构?做 n4(*)[2]()
返回 8 作为答案是有道理的,但是当 fieldnames(n4)
失败了一些我不明白的幕后发生的事情 n4.double()
工作。我可以使用的机制在哪里/什么是.
之后 n4
获取功能/数据?
最佳答案
在 Julia 中,所有泛型函数(即所有常规 Julia 定义的函数)都是结构体。任何结构都可以在 Julia 中调用,因此默认情况下,普通函数只是一个可调用的零字段结构(单例)。换句话说,做foo(x) = x+1
类似于
struct Foo end
const foo = Foo()
(::Foo)(x) = x + 1
这对普通函数很有用,但对于匿名函数,这可能会导致创建大量新类型。例如,你可以这样做:
functions = [x -> x+i for i in 1:1000]
.而不是创建 1000 个新类型,每个类型都有一个新值
i
, Julia 在这里创建了一个包含 i
的类型作为一个字段和 1000 个实例。在你的情况下,而不是
myfunc
为每次调用返回一个新类型并返回该类型的单例实例,它返回一个类型的实例,其字段为 number
, double
和 square
.此外,你完全可以调用字段名,你只需要在类型上调用它:
fieldnames(typeof(myfunc(4)))
.这只是一个优化,你的代码依赖于函数在内存中的表示方式,这感觉有点奇怪。你可能不应该这样做。
关于Julia 函数返回匿名函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62017689/