我对Julia 1.0.0 REPL中typeof
的以下结果感到困惑:
# This makes sense.
julia> typeof(10)
Int64
# This surprised me.
julia> typeof(function)
ERROR: syntax: unexpected ")"
# No answer at all for return example and no error either.
julia> typeof(return)
# In the next two examples the REPL returns the input code.
julia> typeof(in)
typeof(in)
julia> typeof(typeof)
typeof(typeof)
# The "for" word returns an error like the "function" word.
julia> typeof(for)
ERROR: syntax: unexpected ")"
Julia 1.0.0 documentation代表typeof
“获取x的具体类型。”
typeof(function)
的例子真的使我感到惊讶。我期望function
是Julia中的一流对象并具有类型。我想我需要了解Julia中的类型。
有什么建议吗?
修改
根据下面的一些注释问题,这是一个基于小功能的示例:
julia> function test() return "test"; end
test (generic function with 1 method)
julia> test()
"test"
julia> typeof(test)
typeof(test)
基于此示例,我希望typeof(test)
返回generic function
,而不是typeof(test)
。
答案 0 :(得分:5)
需要明确的是,我不是Julia内部构造的硬核用户。以下是一个答案,旨在(希望)直观地解释非核心用户的Julia中的功能。我确实认为,该(非常好)问题也可以从该语言的更多核心开发人员之一提供的更具技术性的答案中受益。另外,这个答案比我想要的要长,但是我使用了多个示例来尝试使事情尽可能直观。
正如评论中所指出的那样,function
本身是保留关键字,不是本身本身的实际功能,因此与实际问题正交。该答案旨在解决您对该问题的修改。
由于Julia v0.6 +起,Function
是抽象超型,与Number
是抽象超型的方式非常相似。所有功能,例如mean
,用户定义的函数和匿名函数是Function
的子类型,就像Float64
和Int
是Number
的子类型一样。< / p>
此结构是经过精心设计的,具有多个优点。
首先,出于我不完全理解的原因,以这种方式构造函数是允许Julia中的匿名函数与Base
中的内置函数一样快地运行的关键。如果您想了解更多有关此内容的信息,请参见here和here。
第二,由于每个函数都是其自己的子类型,因此您现在可以分派特定的函数。例如:
f1(f::T, x) where {T<:typeof(mean)} = f(x)
和:
f1(f::T, x) where {T<:typeof(sum)} = f(x) + 1
函数f1
因此,鉴于上述所有原因,例如typeof(sum)
返回typeof(sum)
,特别是考虑到typeof(Float64)
返回DataType
吗?这里的问题是,从语法的角度来看,粗略地说,sum
需要同时满足两个目的。它必须既是一个值,例如1.0
,尽管它用于在某些输入上调用sum
函数。但是,它也必须是类型名称,例如Float64
。
很明显,它不能同时做两个。因此sum
本身的行为就像一个值。您可以编写f = sum ; f(randn(5))
来查看其行为如何像一个值。但是我们还需要一种表示sum
类型的方法,这种类型不仅适用于sum
,而且适用于任何用户定义的函数和任何匿名函数。开发人员决定使用(可能是最简单的)选项,并将sum
的类型按字面意义打印为typeof(sum)
,因此您会观察到这种行为。同样,如果我写f1(x) = x ; typeof(f1)
,那也将返回typeof(f1)
。
匿名函数有点棘手,因为它们没有这样命名。对于typeof(x -> x^2)
,我们该怎么办?实际发生的情况是,当您构建匿名函数时,该函数将作为临时全局变量存储在模块Main
中,并给出一个用作其查找目的类型的数字。因此,如果您写f = (x -> x^2)
,您将得到类似#3 (generic function with 1 method)
的信息,而typeof(f)
将返回类似getfield(Main, Symbol("##3#4"))
的信息,您可以看到Symbol("##3#4")
是存储在Main
中的此匿名函数的临时类型。 (这样做的副作用是,如果您编写的代码不断地反复任意生成相同的匿名函数,则最终将导致内存溢出,因为它们实际上都存储为各自类型的单独全局变量。)
将所有这些与Function
超类型相关联,您会注意到typeof(sum) <: Function
返回true
,表明sum
的类型,也称为{{1} }实际上是typeof(sum)
的子类型。还要注意,Function
返回typeof(typeof(sum))
,与DataType
返回typeof(typeof(1.0))
的方式几乎相同,这表明DataType
的实际行为就像一个值。>
现在,考虑到我所说的一切,您问题中的所有示例现在都说得通了。 sum
和typeof(function)
返回错误,因为typeof(for)
和function
是保留语法。 for
和typeof(typeof)
分别正确返回typeof(in)
和typeof(typeof)
,因为typeof(in)
和typeof
都是函数。当然请注意,in
返回typeof(typeof(typeof))
。