Julia 函数返回匿名函数

ITA*_*ITA 8 julia

我试图理解一段相对简单的代码,但我不太能理解发生了什么(我是来自 Python/Matlab 背景的 Julia 新手)。

function myfunc(number::Integer)
    double() = 2*number
    square() = number^2
    return _ -> (number, double, square)
end
Run Code Online (Sandbox Code Playgroud)

我知道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))
Run Code Online (Sandbox Code Playgroud)

第一行n4引用匿名函数本身,而在第二行中,匿名函数使用参数调用50并执行它应该做的事情:丢弃 50 并返回包含定义它的数据的元组。

我不明白的是我如何能够做到:

julia> n4.square
(::var"#square#11"{Int64}) (generic function with 1 method)

julia> n4.square()
16
Run Code Online (Sandbox Code Playgroud)

这事实上n4是指一个匿名函数对象n4.numbern4.doublen4.square是一个让我吃惊。n4表现得如何,好像它是一个结构?做n4(*)[2]()返回 8 作为答案是有道理的,但是当fieldnames(n4)失败时,幕后会发生一些我不明白的n4.double()事情。凡/什么由我能够使用该机制是.n4得到的功能/数据?

Jak*_*sen 8

在 Julia 中,所有泛型函数(即所有常规 Julia 定义的函数)都是结构体。任何结构都可以在 Julia 中调用,因此默认情况下,普通函数只是一个可调用的零字段结构(单例)。换句话说,做

foo(x) = x+1

类似于

struct Foo end
const foo = Foo()
(::Foo)(x) = x + 1
Run Code Online (Sandbox Code Playgroud)

这对普通函数很有用,但对于匿名函数,这可能会导致创建大量新类型。例如,你可以这样做: functions = [x -> x+i for i in 1:1000]

与创建 1000 个新类型不同,每个类型都有一个新值i,Julia 在这里创建了一个包含i作为字段的单一类型和 1000 个实例。

在您的情况下,它不是myfunc为每个调用返回一个新类型并返回该类型的单例实例,而是返回一个类型的实例,其中包含字段number,doublesquare

此外,您完全可以调用 fieldnames,您只需要在 type: 上调用它fieldnames(typeof(myfunc(4)))

这只是一个优化,你的代码依赖于函数在内存中的表示方式,这感觉有点奇怪。你可能不应该这样做。