# Is there a good reason why \`!(Tuple \<: AbstractVector)\`?

**URL:** https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461
**Category:** Internals & Design
**Created:** [May 1, 2017, 4:25pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461 "2017-05-01T16:25:36Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [May 1, 2017, 4:25pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/1 "2017-05-01T16:25:36Z")

</div>

I’m assuming there is, but I don’t know what that might be. I’m pretty sure tuples implement everything in the `AbstractVector` interface except for `size` (and I see no reason why you couldn’t just do `size(t::Tuple)=tuple(length(t))`). Of course, the principle difference between vectors and tuples is that vectors are associated with a single element type, however tuples still seem to me like they are `AbstractVector{<:Any}`s. In fact (at least in v0.6) `eltype` is defined for tuples.

More often than not I find `!(Tuple <: AbstractVector)` to be an annoyance.

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [May 1, 2017, 4:59pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/2 "2017-05-01T16:59:18Z")

</div>

Tuples are the only covariant datatype in Julia, all others are invariant. Thus being its own type seems reasonable (necessary?).

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [May 1, 2017, 5:16pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/3 "2017-05-01T17:16:14Z")

</div>

Some discussion here: [https://github.com/JuliaLang/julia/pull/21096](https://github.com/JuliaLang/julia/pull/21096)

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [May 1, 2017, 5:35pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/4 "2017-05-01T17:35:38Z")

</div>

Tuples are immutable. The array interface assumes mutability (`setindex!`). If you put tuples into codes for `AbstractArray`s, you can’t expect it to work. Maybe there should be `AbstractImmutableArray`

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [May 1, 2017, 5:38pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/5 "2017-05-01T17:38:19Z")

</div>

It’s just fine to have `AbstractArray`s that don’t support `setindex!`. See: Ranges.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [May 1, 2017, 5:39pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/6 "2017-05-01T17:39:41Z")

</div>

True… that gets me all the time.

---

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [May 1, 2017, 5:41pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/7 "2017-05-01T17:41:31Z")

</div>

> [@mauro3](#):
>
> Tuples are the only covariant datatype in Julia

Woah, I did not realize until just now that `Tuple`s are covariant. Now _that_ is confusing, what is the reason for _that_?

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [May 1, 2017, 5:54pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/8 "2017-05-01T17:54:11Z")

</div>

Dispatch itself is covariant. Tuples are the data structure that represent argument lists.

---

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [May 1, 2017, 7:10pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/9 "2017-05-01T19:10:20Z")

</div>

> [@mbauman](#):
>
> Dispatch itself is covariant. Tuples are the data structure that represent argument lists.

That makes sense. It’s now bugging me that it’s impossible to declare any other covariant types in Julia, or am I wrong about that?

It’s not something that I really see the need for, it’s just bothering me for purely academic reasons.

---

<div class="post-metadata">

### Author: ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)
#### Post date: [May 2, 2017, 9:27am UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/10 "2017-05-02T09:27:52Z")

</div>

Also , what `T` would it be if `Tuple{Int,String} <: AbstractVector{T}`?

---

<div class="post-metadata">

### Author: ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)
#### Post date: [May 2, 2017, 10:16am UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/11 "2017-05-02T10:16:00Z")

</div>

Academically speaking, you can make a hacky system of “tagged” tupples like

```julia
struct MyTypeTag; end
const MyType = Tuple{MyTypeTag, Integer, AbstractVector}
MyType(a::Integer, b::AbstractVector) = (MyTypeTag(), a, b)

```

and probvide other constructors and methods for `MyType` as you please. You however loose access to getfield. But it’s fully compatible with multiple dispatch, and macros could make this easy.

I say “academic” because there’s no support for a covariant `Array` (I guess the relatively modern untyped comprehensions come close), so you can only get so far by assuming that types are covariant. But it’s a fun mind experiment to think of how this could play out if covariance was supported/assumed at the language level (for structs and `Buffer`, say).

---

<div class="post-metadata">

### Author: ![martinholters](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martinholters/32/3690_2.png) [@martinholters](https://discourse.julialang.org/u/martinholters)
#### Post date: [May 2, 2017, 11:30am UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/12 "2017-05-02T11:30:07Z")

</div>

IMHO, covariance would be plausible for immutables, but does not really play well with inheritance from abstract types. E.g. if you accept a `Tuple{Integer,Integer}`, then of course a `Tuple{Int16,Int16}` is fine; after all, any element you can obtain from the tuple `isa Integer`, and the question whether you can store another `Integer` than `Int16` is irrelevant for an immutable `Tuple`. The same would hold for hypothetical `ImmutableVector{Integer}`. But now if `ImmutableVector{T} <: AbstractVector{T}`, then `ImmutableVector{Int16} <: AbstractVector{Int16}` and `ImmutableVector{Integer} <: AbstractVector{Integer}`, and - with covariance allowed - `ImmutableVector{Int16} <: ImmutableVector{Integer}`. So transitivity would mean that `ImmutableVector{Int16} <: AbstractVector{Integer}`, which also makes sense, but might be quite are to deduce is slightly more involved cases.

---

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [May 2, 2017, 1:41pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/13 "2017-05-02T13:41:07Z")

</div>

> [@dlfivefifty](#):
>
> Also , what T would it be if Tuple{Int,String} \<: AbstractVector{T}?

In that case `T` would be `Any`. This would be consistent with the existing behavior of `eltype` when applied to tuples. However, note that `eltype((1,UInt(1))) == Integer`, so it does seem like a _slightly_ complicated issue to infer the `AbstractVector` types (though it’d still be well-defined from a graph theory perspective I think).

Anyway, I think the current situation of having invariant types but being able to do things like `AbstractVector{<:Integer}` works quite well (especially now that we have this shorthand notation in 0.6!), and there is probably less chance for confusion than there would be if there were covariant types flying around.

The original motivation of my post was purely practical: in most cases if I have a function that takes an `AbstractVector`, I’m also ok with it taking a `Tuple`. I suspect that’s true for everyone in most circumstances. Maybe it would be nice to, in `Base`, define something like

```julia
const AbstractAbstractVector{T} = Union{AbstractVector{T}, Tuple{Vararg{T}}}

```

(the name is kind of a joke). However, the subtyping of this thing gets damn confusing because of the covariance of tuples, so this is probably a bad idea.

---

<div class="post-metadata">

### Author: ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)
#### Post date: [May 4, 2017, 10:07am UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/14 "2017-05-04T10:07:33Z")

</div>

For mutable covariant arrays I would see it as inference’s job to prove a given element type for the array and allow efficient code for that case. When you can’t prove absolutely what types get put into `setindex!`, then you must leave the elements boxed (e.g. `Any`). To me that seems “fine”: Julia already follows a dynamic semantic but with inference for optimization, so it’s more of the same.

The bigger question is if such a covariant semantic is worthwhile or desirable at all. As stated above, it might be too confusing. It might make the FFI harder. I dunno.

For `AbstractAbstractArray` I think what you want is some kind of trait indicating that you can index it similar to an array, i.e. You certify your type follows some interface for `getindex`, say. My personal prediction is that traits will eventually (in the longer term) become a part of Julia, and maybe then it will be easier to use tuples as simple vector-like storage.

---

<div class="post-metadata">

### Author: ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)
#### Post date: [May 4, 2017, 10:15am UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/15 "2017-05-04T10:15:16Z")

</div>

> [@ExpandingMan](#):
>
> The original motivation of my post was purely practical: in most cases if I have a function that takes an AbstractVector, I’m also ok with it taking a Tuple. I suspect that’s true for everyone in most circumstances.

I’ve needed something like this as well and also use Unions as a fix. I think there is some kind of plan to have traits to cover this type of use case, though I’m not sure what the priority on that is. See also

> **[GitHub - mauro3/SimpleTraits.jl: Simple Traits for Julia](https://github.com/mauro3/SimpleTraits.jl)**
>
> Simple Traits for Julia. Contribute to mauro3/SimpleTraits.jl development by creating an account on GitHub.

and

> <https://github.com/JuliaLang/julia/pull/13222>
>
> This PR implements macro-sugar for Holy Traits (HT). This is \[SimpleTraits.jl\](…https://github.com/mauro3/SimpleTraits.jl) ported to Base (so to check it out, cloning SimpleTraits will be faster than building this PR).
> 
> The idea behind this PR is to make HT easier to use. An added benefit is that this marks them, so they could be easily updated once a more proper trait system is in place. (I suspect that the semantics of a trait-system-to-be will be a superset of HT, so the migration should be reasonably easy.) At the moment only the linear-indexing HT is in Base, but judging by the chat on julia-issues this may change (e.g. #13157, #10385, ...), thus a more structured approach may make sense.
> 
> The readme of \[SimpleTraits.jl\](https://github.com/mauro3/SimpleTraits.jl) gives an overview of the functionality. The short is:
> 
> \`\`\` julia
> @traitdef LinearFastTr{X}
> @traitimpl LinearFastTr{Array}
> @traitimpl LinearFastTr{Range}
> @traitfn f1{X\<:AbstractArray; LinearFastTr{X}}(a::X) = 1
> @traitfn f1{X\<:AbstractArray; !LinearFastTr{X}}(a::X) = 2
> f1(1:3) # -\> 1
> f1(\[1,2\]) # -\> 1
> f1(speye(2)) # -\> 2
> \`\`\`
> 
> which is quite a bit shorter and more readable than the manual implementation (as done for \`LinearIndexing\` in Base):
> 
> \`\`\` julia
> \# the trait
> abstract LinearIndexing
> immutable LinearFast \<: LinearIndexing end
> immutable LinearSlow \<: LinearIndexing end
> 
> \# the trait-implementation
> linearindexing(A::AbstractArray) = linearindexing(typeof(A))
> linearindexing{T\<:AbstractArray}(::Type{T}) = LinearSlow()
> linearindexing{T\<:Array}(::Type{T}) = LinearFast()
> linearindexing{T\<:Range}(::Type{T}) = LinearFast()
> 
> \# a traitfunction
> @inline f2(A::AbstractArray) = f2(linearindexing(A), A)
> f2(::LinearFast, A::AbstractArray) = 1
> f2(::LinearSlow, A::AbstractArray) = 2
> 
> \# use it
> f2(1:3) # -\> 1
> f2(\[1,2\]) # -\> 1
> f2(speye(2)) # -\> 2
> \`\`\`
> 
> For testing and illustrating, I've implemented some HT usages in Base (which should be purged again). The next step would be to refactor the \`LinearIndexing\` HT (the only HT currently used in Base, as far as I know). However, before embarking on that reasonably big task, I have this question: \_Does this PR have any chance of being merged?\_ (Any other comments are of course welcome too!)
> 
> Other things to consider:
> \- function/macro names?
> \- should the HT-interface be exported?
> \# TODO
> \- \[\] refactor \`LinearIndexing\` trait
> \- \[\] add documentation
> \- \[\] move to earlier in the bootstrap?
> \- \[\] add doc-capability to traitfn after #13006
> 
> Remove:
> \- \[\] example HTs
> \- \[\] bootstrap tests

@mauro3 Do you have any updates on this?

---

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [May 4, 2017, 2:08pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/16 "2017-05-04T14:08:34Z")

</div>

Interesting. I didn’t even know about traits. It never ceases to blow my mind how much one can achieve with metaprogramming. As I get more used to it, I find it harder to imagine using programming languages without it.

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [May 4, 2017, 9:04pm UTC](https://discourse.julialang.org/t/is-there-a-good-reason-why-tuple-abstractvector/3461/17 "2017-05-04T21:04:27Z")

</div>

Not really any updates. SimpleTraits.jl is ready for use and is being used. I am not working on anything in Julia Base and I don’t know of anyone else (but I don’t have much of a grasp on what is going on). According to Stefan’s JuliaCon2016 talk, traits are scheduled for Julia 2.0.
