# What's with the invariant parametric types gotcha?

Consider:

``````julia> foo(x::Vector{Integer}) = "bar"
foo (generic function with 1 method)

julia> foo([1, 2, 3])
ERROR: MethodError: no method matching foo(::Array{Int64,1})
Closest candidates are:
foo(::Array{Integer,1}) at REPL[1]:1
Stacktrace:
[1] top-level scope at REPL[2]:1

julia> foo(x::Vector{<:Integer}) = "bar"
foo (generic function with 2 methods)

julia> foo([1, 2, 3])
"bar"
``````

Of course, this is documented: Types · The Julia Language

Still, in my mind I could almost audibly hear Julia saying “ha ha, gotcha!” when I first learned this. What is the reason for this syntax?

Is it even possible to call `foo(x::Vector{Integer}) = "bar"`? If not, why not just implicitly add the `<:` syntax so it “just works”?

Is it just a syntax decision? Maybe the designers of the language wanted to be explicit by requiring the `<:` syntax? If so, that’s understandable, even though I may or may not agree*.

* I don’t agree or disagree with any syntax decisions. I like Julia, and I like its syntax. And in general I consider syntax issues to be very low on the list of things that matter, so I don’t even bother forming an opinion on most syntax debates.

Yes. Just call:

``````foo(Integer[1, 2, 3])
``````
2 Likes

No, the syntax really isn’t the core of the issue here. A `Vector{Integer}` is a real type, and one you might even use at some point, it’s just that `[1, 2, 3]` doesn’t give you one.

A `Vector{Integer}` is a vector in which every element can be a (potentially different) subtype of `Integer`:

``````julia> x = Vector{Integer}()
Integer[]

julia> push!(x, 1)
1-element Array{Integer,1}:
1

julia> push!(x, big(2)^big(100))
2-element Array{Integer,1}:
1
1267650600228229401496703205376
``````

This is different from `Vector{Int64}` in which every element is exactly the concrete type `Int64`. It’s also different from `Vector{<:Integer}` which is a set of types describing any `Vector` whose element type is any subtype of `Integer`. `Vector{Int64}` and `Vector{Integer}` are both members of that set:

``````julia> Vector{Int64} <: Vector{<:Integer}
true

julia> Vector{Integer} <: Vector{<:Integer}
true
``````

but they have no relationship to one another otherwise:

``````julia> Vector{Int64} <: Vector{Integer}
false
``````
8 Likes

I see. So there is at least a reason for the syntax. Because you need some way to distinguish between, well, a `Vector{Integer}` and a `Vector{<:Integer}`. I’m satisfied with that explanation.

1 Like