`Tuple` 中的 `Vararg` 类型参数的疑问


#1

首先定义一些变量

julia> T1 = Tuple{Vararg{T, 2}} where T; T2 = Tuple{Vararg{T, 2} where T};

我感觉应该有 T1 == T2,可是在 Julia 中我得到了以下结果:

julia> T1 == T2
false

julia> T1 <: T2
true

julia> T1 >: T2
false

如果把 Vararg 替换成 Array,倒是会符合我的预测:

julia> (Tuple{Array{T, 2}} where T) == Tuple{Array{T, 2} where T}
true

以上关系成立的原因是什么,或者说这是一个 bug 吗?


#2

不带分号就能看出差别

julia> T1 = Tuple{Vararg{T, 2}} where T
Tuple{Vararg{T,2}} where T

julia> T2 = Tuple{Vararg{T, 2} where T}
Tuple{Any,Any}

julia> T1 == T2
false

julia> (1, 2) isa T1
true

julia> (1, 2) isa T2
true

julia> (1, 2.0) isa T1
false

julia> (1, 2.0) isa T2
true

T1 限定了两个参数必须是一样的类型;而 T2 两个参数的类型可以不一样


#3

我就是对 T2 的值感到奇怪,我以为会等于 Tuple{T, T} where T(与 T1 相等),实际上却等于 Tuple{T, S} where {T, S}(与 Tuple{Any, Any} 相等),T2 定义里的类型约束平白无故就没了。此外,我还发现了一个奇怪的现象,见此 issue


#4
@test isequal_type(Type{Tuple{Vararg{Int,N}} where N}, Type{Tuple{Vararg{Int,N} where N}})
@test Type{Tuple{Vararg{Int,N}} where N} !== Type{Tuple{Vararg{Int,N} where N}}

test 里测试了 where N 的位置是没有影响的,不知道为什么没有测试 where T

目前 v1.1.1 的情况

julia> Type{Tuple{Vararg{Int,N}} where N} == Type{Tuple{Vararg{Int,N} where N}}
true

julia> Type{Tuple{Vararg{T,2}} where T} == Type{Tuple{Vararg{T,2} where T}}
false

let A = Tuple{Vararg{Val{N}, N} where N},
    B = Tuple{Vararg{Val{N}, N}} where N,
    C = Tuple{Val{2}, Val{2}}

    @test isequal_type(A, B)
    @test issub(C, B)
    @test issub(C, A)
end
julia> Tuple{Vararg{Val{N}, N} where N} == Tuple{Vararg{Val{N}, N}} where N
true

julia> Tuple{Vararg{Val{N}, 2} where N} == Tuple{Vararg{Val{N}, 2}} where N
false

julia> Tuple{Vararg{Val{2}, 2}} == Tuple{Vararg{Val{2}, 2}}
true

julia> Tuple{Vararg{Val{N}, 2} where N <: Integer} == Tuple{Vararg{Val{N}, 2}} where N <: Integer
false

不是很懂


又看到一个相关的测试,不过没搞清楚 @testintersect 宏的功能

    # part of issue #20344
    @testintersect(Tuple{Type{Tuple{Vararg{T, N} where N}}, Tuple} where T,
                   Tuple{Type{Tuple{Vararg{T, N}}} where N where T, Any},
                   Bottom)

#5

T2的约束是有的,如果定义成T2 = Tuple{Vararg{T, 2} where T<:Real};
那么T2的两个元素必须为Real,可能是两个int的组合,也可能是int和float的组合,这点手册里面有说道UnionAll Types,如果是Tuple{T, S} where {T, S},两个元素可一点关联都没有。


#6

楼主想说的是,像 T2 应该和 T1 一样,有两个参数都是同类型的约束。
而不是两个 Any,两个 Any 就可以是不一样的类型(例子见我的第一个回复)。

julia> T2 = Tuple{Vararg{T, 2} where T}
Tuple{Any,Any}