首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Julia typeof的令人费解的结果

Julia typeof的令人费解的结果
EN

Stack Overflow用户
提问于 2018-09-16 15:16:04
回答 1查看 1K关注 0票数 5

我对typeof在Julia 1.0.0 REPL中的以下结果感到困惑:

代码语言:javascript
复制
# 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 ")"

对于typeof,Julia1.0.0 documentation说“获取x的具体类型”。

typeof(function)示例是真正让我惊讶的示例。我希望function是Julia中的一级对象,并且有一个类型。我想我需要理解Julia中的类型。

有什么建议吗?

编辑

根据下面的一些评论问题,这里有一个基于一个小函数的示例:

代码语言:javascript
复制
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)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-16 19:11:00

需要说明的是,我并不是Julia内部机制的铁杆用户。下面的答案旨在(希望)直观地解释Julia中为非铁杆用户提供了哪些功能。我确实认为这个(非常好的)问题也可以从该语言的核心开发人员提供的更具技术性的答案中受益。此外,这个答案比我希望的要长,但我已经使用了多个示例来尝试使事情尽可能直观。

正如评论中所指出的,function本身是一个保留的关键字,本身并不是一个实际的函数,因此与实际问题是正交的。此答案旨在解决您对该问题的编辑。

由于Julia v0.6+,Function是一个抽象的超类型,就像Number是一个抽象的超类型一样。所有函数,例如mean、用户定义函数和匿名函数,都是Function的子类型,就像Float64IntNumber的子类型一样。

这种结构是经过深思熟虑的,有几个优点。

首先,出于我不完全理解的原因,以这种方式构造函数是允许Julia中的匿名函数像Base中的内置函数一样快运行的关键。如果您想了解更多关于这方面的知识,请参阅herehere作为起点。

其次,因为每个函数都是它自己的子类型,所以现在可以对特定的函数进行调度。例如:

代码语言:javascript
复制
f1(f::T, x) where {T<:typeof(mean)} = f(x)

和:

代码语言:javascript
复制
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中的这个匿名函数的临时类型。(这样做的一个副作用是,如果您编写的代码一遍又一遍地随意生成相同的匿名函数,您最终会溢出内存,因为它们实际上都是作为各自类型的独立全局变量存储的-然而,这不会阻止您在函数中执行类似for n = 1:largenumber ; findall(y -> y > 1.0, x) ; end的操作,因为在这种情况下,匿名函数只在编译时编译一次)。

将所有这些都与Function超类型联系起来,您将注意到typeof(sum) <: Function返回true,这表明sum的类型,也就是typeof(sum),确实是Function的一个子类型。还要注意,typeof(typeof(sum))返回DataType的方式与typeof(typeof(1.0))返回DataType的方式非常相似,这说明了sum实际上是如何像一个值一样工作的。

现在,考虑到我所说的所有内容,您问题中的所有示例现在都有意义了。typeof(function)typeof(for)按其应有的方式返回错误,因为functionfor是保留语法。typeof(typeof)typeof(in) (分别)正确地返回typeof(typeof)typeof(in),因为typeofin都是函数。当然,请注意typeof(typeof(typeof))返回DataType

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52351852

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档