考虑以下代码:
julia> function foo(x::Float64)::Float64
return 2x
end
foo (generic function with 1 method)
julia> typeof(foo)
typeof(foo)
typeof(foo)
肯定是有原因的不会返回更有意义的东西,例如 (Float64 -> Float64)
.它是什么?我在看
Zygote
code 时遇到了这个问题.
最佳答案
当你写 typeof(foo)
您正在询问 的类型功能 foo
.这个函数可以有多个方法 (类型稳定与否 --- 但这是另一个问题),并且这些方法具有不同的签名(参数类型),对于其中一些方法,编译器可能能够推断出返回类型,而对于其他方法则可能不能(而您不应该依赖它 AFAICT --- 只是假设大部分时间编译器都做正确的工作)。
举个例子,考虑一下这段代码(1个函数,2个方法):
julia> f1(::Int) = 1
f1 (generic function with 1 method)
julia> f1(::Bool) = 2
f1 (generic function with 2 methods)
julia> typeof(f1)
typeof(f1)
julia> methods(f1)
# 2 methods for generic function "f1":
[1] f1(::Bool) in Main at REPL[21]:1
[2] f1(::Int64) in Main at REPL[20]:1
现在引用您所写的返回值规范:f(x)::Float64 = x
它们不仅仅是断言。 Julia 实际上做了两件事:这是相关的,例如在我的函数中
f
上面你可以写:julia> f(1)
1.0
julia> f(true)
1.0
并且您可以看到发生了转换(不仅是断言)。这种风格在类型不稳定的代码中非常相关(例如,当使用
DataFrame
是一种类型不稳定的数据结构时),因为这样的断言可以帮助“打破类型不稳定链”在你的代码中(如果你有它的某些部分不是类型稳定)。编辑
Could this not be resolved by using
Union{Int, Bool} -> Int
? forf1
, for example? And similarly for type instability? I guess that would require the code to be compiled for all input types and therefore lose the advantages of JIT?
但是如果对于
Int
Int
被退回并为 Bool
Bool
被退回?考虑例如identity
功能。也拿下面的例子:
julia> f(x) = ("a",)[x]
f (generic function with 1 method)
julia> @code_warntype f(2)
Variables
#self#::Core.Compiler.Const(f, false)
x::Int64
Body::String
1 ─ %1 = Core.tuple("a")::Core.Compiler.Const(("a",), false)
│ %2 = Base.getindex(%1, x)::String
└── return %2
julia> Base.return_types(f)
1-element Array{Any,1}:
Any
@code_warntype
正确识别如果此函数返回某些内容,则保证为 String
然而,return_types
正如 Przemysław 建议的那样告诉您它是 Any
.所以你可以看到这是一件很难的事情,你不应该盲目地依赖它——假设它是由编译器来决定它可以推断出什么。特别是 - 出于性能原因 - 编译器可能会放弃进行推理,即使理论上这是可能的。在您的问题中,您可能指的是例如Haskell 提供,但在 Haskell 中有一个限制,即函数的返回值可能不取决于传递的参数的运行时值,而仅取决于参数的类型。 Julia 中没有这样的限制。
关于function - Julia 中的函数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63618640/