朱莉娅(Julia):匹配属于联盟的任何类型

时间:2018-11-27 15:39:14

标签: julia

我有一个Union{Type1, Type2, Type3},它与类型为那些类型之一的所有值匹配。但是我该如何匹配类型本身?

MyU = Union{Float64, Int, Array}
a::MyU = 3.5 # works
a = 5 # works
a = [1, 2, 3] # works
# but of course
a = Float64 # nope
a = Int # nope
a = Array # nope

对于普通类型,通常可以通过Type{MyType}来实现,其唯一值为MyType。但是Type{MyU}仅匹配MyU,而不匹配它包含的类型。我该如何匹配?

我当然可以只使用DataType,但这有两个问题:

  1. 它匹配任何类型,不仅是我想要的类型。
  2. 它与UnionAll类型不匹配,例如Array

我目前的解决方法是Union{DataType,UnionAll},但是如果我在Union中包含另一个MyU或其他一些非混凝土类型,那么这是一个丑陋的hack,它必然会崩溃并烧毁。 / p>

我的另一个解决方案是像这样建立第二个并行Union:

MyU = Union{Float64, Int, Array}
MyUT = Union{Type{Float64}, Type{Int}, Type{Array}}

它确实可以工作并且更加严格,但是它也很丑陋,并且通过手动保持人与人之间的同步来引入人为错误的可能性很大。

1 个答案:

答案 0 :(得分:2)

您可以考虑采用以下方法来避免使用宏(这可能会很棘手):

gettypes(u::Union) = [u.a; gettypes(u.b)]
gettypes(u) = [u]
typewrap(u) = Union{[Type{v} for v in gettypes(u)]...}

然后:

julia> MyU = Union{Float64, Int, Array}
Union{Float64, Int64, Array}

julia> MyUT = typewrap(MyU)
Union{Type{Array}, Type{Float64}, Type{Int64}}

编辑

作为附加说明,您可以像这样将gettypes定义为一个衬纸:

gettypes(u) = u isa Union ? [u.a; gettypes(u.b)] : [u]

编辑2

或更简单,没有中间数组:

typewrap(u) = u isa Union ? Union{Type{u.a}, typewrap(u.b)} : Type{u}