获取Julia中容器类型而不是元素类型的惯用方法是什么?

huangapple go评论56阅读模式
英文:

Idiomatic way to get the container type instead of element type in Julia?

问题

我想要实现以下的行为。

container_type(::Type{Vector{T}}) where T = Vector
container_type(::Type{Matrix{T}}) where T = Matrix

当然,我不希望硬编码每个具体类型。首先,我想要能够以编程方式为AbstractVector的每个子类型执行此操作。我尝试了以下方法。

container_type(::Type{V{T}}) where {V <: AbstractVector, T} = V

但是,这会导致TypeError,因为类型变量不能嵌套。我的下一个猜测是遍历AbstractVector的所有子类型。以下方法适用于AbstractVector子类型的有限子集。

for vec_type in nameof.(subtypes(AbstractVector))
    try
        @eval begin
            container_type(::Type{$(vec_type){T}}) where T = $(vec_type)
        end
    catch
        for (exc, bt) in current_exceptions()
            showerror(stderr, exc, bt)
        end
    end
end

需要try-catch块,因为subtypes(AbstractVector)中的某些类型由模块作用域。

nameof函数会丢弃模块名称,这就是为什么它们在@eval块中无法找到的原因。

我目前被困在这一点。如何解决这个错误?在这里是否有更好的方法?

英文:

I want to implement the following behavior.

container_type(::Type{Vector{T}}) where T = Vector
container_type(::Type{Matrix{T}}) where T = Matrix

But, of course I do not want to hard-code every concrete type. For starters, I want to be able to programmatically do this for every subtype of AbstractVector. I tried the following.

container_type(::Type{V{T}}) where {V <: AbstractVector, T} = V

But, this results in a TypeError because type variables cannot be nested. My next guess is iterating over all the subtypes of AbstractVector. The following works for a limited subset of the subtypes of AbstractVector

for vec_type in nameof.(subtypes(AbstractVector))
    try
        @eval begin
            container_type(::Type{$(vec_type){T}}) where T = $(vec_type)
        end
    catch
        for (exc, bt) in current_exceptions()
            showerror(stderr, exc, bt)
        end
    end
end

The try-catch block is required because some of the types in subtypes(AbstractVector) are scoped by modules.

julia> subtypes(AbstractVector)
20-element Vector{Any}:
 AbstractRange
 Base.ExceptionStack
 Base.LogicalIndex
 Base.MethodList
 Base.ReinterpretArray{T, 1, S} where {T, S}
 Base.ReshapedArray{T, 1} where T
 BitVector (alias for BitArray{1})
 CartesianIndices{1, R} where R<:Tuple{OrdinalRange{Int64, Int64}}
 Core.Compiler.AbstractRange
 Core.Compiler.BitArray{1}
 Core.Compiler.ExceptionStack
 Core.Compiler.LinearIndices{1, R} where R<:Tuple{Core.Compiler.AbstractUnitRange{Int64}}
 Core.Compiler.MethodList
 DenseVector (alias for DenseArray{T, 1} where T)
 LinearIndices{1, R} where R<:Tuple{AbstractUnitRange{Int64}}
 PermutedDimsArray{T, 1} where T
 AbstractSparseVector (alias for SparseArrays.AbstractSparseArray{Tv, Ti, 1} where {Tv, Ti})
 SubArray{T, 1} where T
 Tables.EmptyVector
 Test.GenericArray{T, 1} where T

and nameof discards the module names altogether

julia> subtypes(AbstractVector) .|> nameof
20-element Vector{Symbol}:
 :AbstractRange
 :ExceptionStack
 :LogicalIndex
 :MethodList
 :ReinterpretArray
 :ReshapedArray
 :BitArray
 :CartesianIndices
 :AbstractRange
 :BitArray
 :ExceptionStack
 :LinearIndices
 :MethodList
 :DenseArray
 :LinearIndices
 :PermutedDimsArray
 :AbstractSparseArray
 :SubArray
 :EmptyVector
 :GenericArray

which is why they cannot be found in the @eval block.

I have been stuck at this point. How can I work around this error? Is there any other approach that might work better here?

答案1

得分: 1

Here's the translation of the code part you provided:

也许你想要:

ctype(::T) where T <: AbstractArray = T.name.wrapper

现在你可以这样做:

julia> ctype(1:4)
UnitRange

julia> ctype([7, 8, 9])
Array

请注意,VectorMatrixArray 的别名,而不是类型(具有不同维度参数的别名),因此,如果你想区分它们,你需要直接获取类型。

ctype2(::T) where T <: AbstractVector = T

请注意,这是代码的翻译部分,没有其他内容。

英文:

Perhaps you want:

ctype(::T) where T &lt;:AbstractArray = T.name.wrapper

Now you can do:

julia&gt; ctype(1:4)
UnitRange

julia&gt; ctype([7,8,9])
Array

Note that Vector and Matrix are aliases to Array rather than types (aliases with different dimension parameters) so if you want to distinguish between the two you need to get the type directly.

ctype2(::T) where T &lt;:AbstractVector = T

huangapple
  • 本文由 发表于 2023年2月23日 21:28:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545502.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定