首页 > 解决方案 > 当函数体中没有指定泛型类型参数时,如何访问它?

问题描述

假设我有

struct X{T} end

和一个函数调度,如果方法签名中没有指定,X我如何访问函数体内部?TIE

function foo(x::X)
    # can i get T in here?
end

这是对 julialang 松弛问题的改写:https ://julialang.slack.com/archives/C6A044SQH/p1568651904113000

要获得访问权限,只需填写此表格:https ://slackinvite.julialang.org

标签: julia

解决方案


解决这个问题的最好方法是定义一个访问器函数:

getparam(::X{T}) where {T} = T

然后可以做

function foo(x::X)
    T = getparam(x)
    ...
end

只要您没有通过解释器运行 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
}

如您所见,编译器能够发现它可以在编译时将调用替换为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

哎呀,太慢了!为了比较,

julia> bar(x) = x + 1
bar (generic function with 1 method)

julia> @btime bar(rand(Int))
  9.746 ns (0 allocations: 0 bytes)
5990190339309662951

推荐阅读