Problem with the Tuple type

Hi! I’m new to this forum, though not to Julia. I have a question.
Recently I tried to build a function meant to accept as input only vectors of n-tuples (without specifying n).

For example, consider the following:

X = [(i,j) for i in 1.:2 for j in 1:3.]

whose type is Array{Tuple{Float64,Float64},1}, an array of 2-tuples.

My intention is to have a function like the following:

function test_function(X::Array{Tuple, 1})
    println("good!")
end 

in hopes of allowing the function to take arrays containing Tuples of any kind. In my head this makes sense as Tuple is the parent type of Tuple{Float64,Float64}. I tried to test if this would work using the following two lines.
First, I tested if the elements of X where Tuples, which the should’ve by definition.

julia> isa(X[1], Tuple)
true

sure enough, it works. Then I tested if X itself was an array of tuples

julia> isa(X, Array{Tuple, 1})
false

It turns out it… isn’t? I then tested using the explicit type of the Tuples:

julia> isa(X, Array{NTuple{2, Float64}, 1})
true

It behaves as though Tuple were not the parent type of Tuple{Float64,Float64}. Though testing I found it should be:

julia> Tuple{Float64,Float64} <: Tuple
true

However… Julia does not list any subtypes of the Tuple

julia> subtypes(Tuple)
Type[]

My overall problem is I still can’t build a function that takes only an array of tuples; what I imagine should’ve been the type Array{Tuple,1}, or even Vector{Tuple}, but now I believe something weird is going on with the Tuple type itself.

Thanks to anyone reading! :))

Maybe this helps you

function test_function(X::Array{T, 1}) where T <: Tuple
    println("good!")
end

@show test_function(Vector{Tuple{Float64}}())
@show test_function(Vector{Tuple{Float64, Float64}}())
Vector{<:Tuple}

?

Tuples are weird, but I think this is another case of: Vector{Int} <: Vector{Real} is false??? · JuliaNotes.jl

1 Like

Vectors (and Arrays) are really Vector{T} and Array{T,N}

  • where N is the number of dimensions for the array.
julia> Vector{T} where T
Vector (alias for Array{T, 1} where T)

For a function to accept an argument v, v::Vector{T} where T is any Tuple
and to ignore other argument types:
(edited to use the specific approach that @stevenjg shares next)

julia> istuplevec(v) = false

# istuplevec(v::Vector{T}) where {T allows any kind of Tuple}
# istuplevec(v::Vector{T}) where { isa(T, ::Type{Tuple}) }
# istuplevec(v::Vector{T}) where {T<:Tuple} = true

julia> istuplevec(v::AbstractVector{<:Tuple} = true

julia> istuplevec([(1,2), (3,4)])
true
julia> istuplevec([(1,2), (3,4,5)])
true
julia> istuplevec([(1,2), ("three",4.0,5//1)])
true
julia> istuplevec([(1,2), (3,4), 5])
false

if you want to allow only Vectors of equilength Tuples
where all the elements are of a shared type

julia> isuniformtuplevec(v) = false
julia> isuniformtuplevec(v::AbstractVector{<:NTuple{N}) where {N} = true

julia> isuniformtuplevec([(1,2),(3,4)])
true
julia> isuniformtuplevec([(1,2),(3,4,5)])
false
julia> isuniformtuplevec([(1,2),('3',"4")])
false

This is a FAQ: Why doesn’t it work to declare foo(bar::Vector{Real})…?

Even better, use test_function(X::AbstractVector{<:Tuple}), which allows any type of 1d array (e.g. views of arrays), not just Array, of any type of tuple.

5 Likes