julia - Julia typeof 的令人费解的结果
问题描述
我typeof
对 Julia 1.0.0 REPL 中的以下结果感到困惑:
# 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文档说typeof
“获取 x 的具体类型”。
这个typeof(function)
例子真的让我感到惊讶。我希望 afunction
成为 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)
。
解决方案
需要明确的是,我不是 Julia 内部的铁杆用户。下面是一个旨在(希望)为非核心用户直观地解释 Julia 中的功能的答案。我确实认为这个(非常好的)问题也可以从该语言更核心的开发人员之一提供的更具技术性的答案中受益。此外,这个答案比我想要的要长,但我使用了多个示例来尝试使事情尽可能直观。
正如评论中所指出的,function
它本身是一个保留关键字,本身并不是一个实际的函数,因此与实际问题正交。该答案旨在解决您对该问题的编辑。
由于 Julia v0.6+Function
是一个抽象超类型,与抽象超类型非常相似Number
。所有函数,例如mean
用户定义函数和匿名函数,都是 的子类型Function
,与Float64
和Int
的子类型一样Number
。
这种结构是经过深思熟虑的,并且有几个优点。
首先,由于我不完全理解的原因,以这种方式构造函数是允许 Julia 中的匿名函数与来自Base
. 如果您想了解更多相关信息,请参阅此处和此处作为起点。
其次,因为每个函数都是它自己的子类型,你现在可以在特定的函数上进行调度。例如:
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
print 的类型从字面上看为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
. (这样做的一个副作用是,如果您编写的代码一遍又一遍地任意生成相同的匿名函数,您最终会溢出内存,因为它们实际上都被存储为它们自己类型的单独全局变量 - 但是,这确实不会阻止您for n = 1:largenumber ; findall(y -> y > 1.0, x) ; end
在函数内部执行此类操作,因为在这种情况下,匿名函数仅在编译时编译一次)。
将所有这些都与Function
超类型相关联,您会注意到 return typeof(sum) <: Function
,true
表明sum
akatypeof(sum)
的类型确实是 的子类型Function
。还要注意typeof(typeof(sum))
return DataType
,其方式与 return 非常typeof(typeof(1.0))
相似DataType
,它显示了sum
实际行为如何像一个值。
现在,鉴于我所说的一切,您问题中的所有示例现在都有意义。typeof(function)
并按typeof(for)
应有的方式返回错误,因为function
和for
是保留的语法。typeof(typeof)
andtypeof(in)
正确返回(分别)typeof(typeof)
, and typeof(in)
, 因为typeof
andin
都是函数。当然要注意typeof(typeof(typeof))
返回DataType
。
推荐阅读
- android - 如何为改造实施编写失败的junit测试用例
- c++ - 非数组连续数据块可以通过索引指针访问吗?
- php - Moodle 的 SQL 查询
- java - super.getX() 和简单的 x 之间有区别吗?
- php - 如何通过 PHP 数据库中的 foreach 循环显示相同的日期记录
- assembly - Verified correct shellcode segfaults when run normally; “No such file” in GDB…?
- django - django.db.utils.ProgrammingError: relation "client_apps_externalkeys" does not exist
- python - 'KMeansModel' 对象在 apache pyspark 中没有属性 'computeCost'
- postgresql - PostgreSQL Trigger on last deleted line
- mysql - Mysql - 重新排序/重置位置键