# How to deal with parameters of the type Vector{Tuple}?

Hi,

I’m writing some code where I expect a vector of 2-element tuples but I can’t figure out how to type the parameters in such a way that it’s clear what needs to be passed but not so restrictive that type promotion is thrown out of the window.

I thought the following would work (I simplified the code to the minimum):

``
f(v::Vector{Tuple{Real, Real}}) = v

f([(1, 1)])

``````
But this results in the following error:
``````

ERROR: MethodError: no method matching f(::Array{Tuple{Int64,Int64},1})
Closest candidates are:
f(::Array{Tuple{Real,Real},1}) at none:1
Stacktrace:
[1] top-level scope at none:1

``````
So I thought I'd simplify things as follows:
``````

f(v::Vector{Tuple}) = v

``````
But I get the same type of error:
``````

ERROR: MethodError: no method matching f(::Array{Tuple{Int64,Int64},1})
Closest candidates are:
f(::Array{Tuple,1}) at none:1
f(::Array{Tuple{Real,Real},1}) at none:1
Stacktrace:
[1] top-level scope at none:1

``````
Is there any way that I can type this in such a way that I can actually call the function with any type of Real elements in the tuples?

Stef``````

There you go!

`function f(v::Array{Tuple{T1,T2},1}) where {T1,T2 <: Real}`

I had the same problem yesterday. It turns out that using `Real` as is does not work because of a concept called ‘invariance’ (see the documentation on Types).

So, what you have to do is indicate the compiler that it can be any type that belongs to `Real`. That is what the `where {T1,T2 <: Real}` part means.

4 Likes

Thanks! I’m going to be using this quite a lot I think

I’d go for `f(v::Vector{T}) where T<:Tuple{Real,Real}`. That works because tuples are covariant on parameters (i.e. `T<:Pair{Real,Real}` wouldn’t work the same, and one would need `T<:Pair{<:Real, <:Real})`.

If both tuple elements are expected to have the same type, `f(v::Vector{T}) where {T<:Tuple{R,R}, R<:Real}` may be used.

`Vector{Tuple}` is a concrete type that can hold any tuple, so, from Julia type system point of view, it is different from `Vector{Tuple{Int,Int}}` which can only hold tuples of two `Int`s.

Also, I’d recommend using `AbstractVector` in the signature in case you’d like to pass a vector view at some point in the future.

5 Likes

Note that

``````f(v::Vector{Tuple{T1,T2}}) where {T1,T2 <: Real} = v
``````

does not restrict the parameter `T1`, so for example

``````julia> f([("abc",2)])
1-element Array{Tuple{String,Int64},1}:
("abc", 2)
``````

As suggested above, perhaps what you want is

``````julia> f(v::Vector{<:Tuple{Real,Real}}) = v
f (generic function with 2 methods)

julia> f([(2,1)])
1-element Array{Tuple{Int64,Int64},1}:
(2, 1)

julia> f([(2.0,1)])
1-element Array{Tuple{Float64,Int64},1}:
(2.0, 1)
``````
3 Likes