假设我有
struct X{T} end
Run Code Online (Sandbox Code Playgroud)
以及在上调度的函数,如果未在方法签名中指定函数主体X,如何T在函数主体内部进行访问?即
function foo(x::X)
# can i get T in here?
end
Run Code Online (Sandbox Code Playgroud)
这是对julialang松弛问题的重述:https ://julialang.slack.com/archives/C6A044SQH/p1568651904113000
要获得访问权限,只需填写以下表格:https : //slackinvite.julialang.org
最好的方法是定义一个访问器函数:
getparam(::X{T}) where {T} = T
Run Code Online (Sandbox Code Playgroud)
然后一个人可以做
function foo(x::X)
T = getparam(x)
...
end
Run Code Online (Sandbox Code Playgroud)
只要您没有通过解释器运行julia,就应该在编译时消除所有类型检查。例如:
julia> foo(x::X) = getparam(x) + 1
foo (generic function with 1 method)
julia> foo(X{1}())
2
julia> @code_llvm foo(X{1}())
; @ REPL[24]:1 within `foo'
define i64 @julia_foo_19216() {
top:
ret i64 2
}
julia> @code_llvm foo(X{2}())
; @ REPL[24]:1 within `foo'
define i64 @julia_foo_19221() {
top:
ret i64 3
}
Run Code Online (Sandbox Code Playgroud)
如您所见,编译器能够弄清楚它可以在编译时用替换调用foo(X{2}),3而完全没有运行时开销。
附带说明,这应该有助于说明为什么类型稳定性很重要。如果我们做过类似的事情foo(X{rand(Int)}),则编译器将无法访问类型参数,直到它foo在运行时到达为止,然后需要针对rand(Int)最终评估的结果编译特定的方法,这将非常缓慢:
julia> @btime foo(X{rand(Int)}())
2.305 ms (1962 allocations: 125.49 KiB)
-3712756042116422157
Run Code Online (Sandbox Code Playgroud)
哎呀,这是slooooow!为了比较,
julia> bar(x) = x + 1
bar (generic function with 1 method)
julia> @btime bar(rand(Int))
9.746 ns (0 allocations: 0 bytes)
5990190339309662951
Run Code Online (Sandbox Code Playgroud)