# Argument which is an array of the same subtypes don't match array of super-type

**URL:** <https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712>\
**Category:** General Usage\
**Created:** [November 7, 2020, 12:09am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712 "2020-11-07T00:09:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [November 7, 2020, 12:09am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/1 "2020-11-07T00:09:59Z")

</div>

The short version is that a function typed as

```julia
function x1(Array{SuperType,1})

```

will throw an error if an argument which is an array of _only_ subtypes is passed but not if the array is composed of elements with a mix of subtypes, i.e. if we have subtypes A1 and A2, x1([A1, A2]) works, but x1([A1,A2]) does not work.

I’m not quite sure I understand why.

Here’s a concrete example to demonstrate.

```julia
abstract type Foo end

struct Bar <: Foo
    a :: Int

end

struct Baz <: Foo
    a :: Float64
end

function x1(z::Array{Foo,1})
    println(z)
end

w1 = Bar(1)
w2 = Baz(1.0)

w = [w1, w2]

x1(w)

w = Foo[w1, w1]

x1(w)

w = [w1, w1]

x1(w)

```

```julia
Foo[Bar(1), Baz(1.0)]
Foo[Bar(1), Bar(1)]
briand@quarternote:~/src/julia/fdtd$ julia test5.jl
Foo[Bar(1), Baz(1.0)]
Foo[Bar(1), Bar(1)]
ERROR: LoadError: MethodError: no method matching x1(::Array{Bar,1})
Closest candidates are:
  x1(::Array{Foo,1}) at /home//src/julia/fdtd/test5.jl:12
Stacktrace:
 [1] top-level scope at /home//src/julia/fdtd/test5.jl:29
 [2] include(::Function, ::Module, ::String) at ./Base.jl:380
 [3] include(::Module, ::String) at ./Base.jl:368
 [4] exec_options(::Base.JLOptions) at ./client.jl:296
 [5] _start() at ./client.jl:506
in expression starting at /home//src/julia/fdtd/test5.jl:29

```

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [November 7, 2020, 12:12am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/2 "2020-11-07T00:12:30Z")

</div>

[Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Parametric-Composite-Types) has the very relevent warning

> This last point is _very_ important: even though `Float64 <: Real` we **DO NOT** have `Point{Float64} <: Point{Real}` .

Adapting for this case, what you want is `function x1(Array{<:SuperType,1})` which can be written more simply as `function x1(Vector{<:SuperType})`

---

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [November 7, 2020, 12:20am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/3 "2020-11-07T00:20:12Z")

</div>

I think I may have chosen my example poorly. I think that in my example that Bar and Baz could be defined as parametric types, like Bar{T} so I would have Bar{Int} and Bar{Float64}, but what if Bar and Baz are quite distinct, e.g.

```julia
struct Bar <: Foo
  a :: SomeOtherType
end

```

```julia
struct Baz <: Foo
  b :: YetAnotherType
  c :: AndYetAgain
end

```

---

<div class="post-metadata">

**Author:** ![malacroi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/malacroi/32/19745_2.png) [@malacroi](https://discourse.julialang.org/u/malacroi)\
**Post date:** [November 7, 2020, 2:05am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/4 "2020-11-07T02:05:40Z")

</div>

It doesn’t matter if the subtypes are completely distinct, you just need to make sure that they both support whatever interface `f` uses.

```julia
abstract type Foo end

struct Bar <: Foo
    a :: String
end

struct Baz <: Foo
    b :: Int64
    c :: Float64
end

doFoo(a::Array{<:Foo}) = foreach(println, a)

aBar = [Bar("cow"), Bar("dog")]
aBaz = [Baz(5,sqrt(5)), Baz(6,sqrt(6))]
aFoo = [Bar("goldfish"), Baz(7,0.3)]

doFoo(aBar)
doFoo(aBaz)
doFoo(aFoo)

```

You just wouldn’t want something like,

```julia
doMoreFoo(a::Array{<:Foo,1}) = println(a[1].a)

```

which would fail for an array of all `Baz` and would have questionable efficacy for an array of `Foo`.

---

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [November 7, 2020, 5:37am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/5 "2020-11-07T05:37:03Z")

</div>

I understand the your example but I’m still not clear on why a declaration of

```julia
f(a::Array{Foo,1}

```

fails when I pass it Array{Bar,1} or Array{Baz,1}.

Here’s a much simpler example…

```julia
julia> f(x::Array{Number,1}) = x[1] + x[2]
f (generic function with 2 methods)

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

```

huh ???  
An array of Int64 is an array of Number, isn’t it ? It seems very unintuitive that this causes an error.

Notice how the following works,

```julia
julia> f(x::Number, y::Number) = 2x-y
f (generic function with 2 methods)

julia> f(2,3)
1

julia> f(2.0, 3.0)
1.0

```

Why the array example fails, but this example works seems logically inconsistent.

And just for the sake of completeness,

```julia
julia> f(x::Array{<:Number}) = x[1] + x[2]
f (generic function with 3 methods)

julia> f([1,2])
3

```

oh. drat. I think i get it…

Array{\<:Number} means an array, each element of which, must be a subtype of Number.  
So, Array{Number,1} means something different obviously, but I’m not getting how exactly it’s different…

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [November 7, 2020, 6:21am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/6 "2020-11-07T06:21:59Z")

</div>

Let’s look at an example. Both `Array{Number, 1}` and `Array{Int, 1}` are concrete types, and no concrete type can inherit from another in Julia.

An instance of an `Array{Number, 1}` is an array that you can insert any number into, and can contain any kind of numbers.

This is a property not shared by an `Array{Int, 1}` which can only have `Int`s inserted into it, and which only can contain `Int`s.

They are also represented differently with `Array{Int, 1}` directly containing `Int` while `Array{Number, 1}` contains pointers to `Number`’s

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 7, 2020, 6:34am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/7 "2020-11-07T06:34:18Z")

</div>

The important difference in a glance:

```
julia> isconcretetype(Array{Number, 1})
true
julia> isconcretetype(Array{<:Number, 1})
false

```

The first is a _concrete_ Array that “contains” an abstract parametric type by actually containing pointers to concrete subtypes of that abstract parametric type. Your method simply worked on the concrete type it was made for. Run `println(typeof(w))` for each array you have, you’ll see.  
The second is an abstract type that’s nowhere as specific. It can be an Array of contiguous `Int64` values, it can be an Array of contiguous `Float64` values, or it can be an Array of pointers. In fact:

```
julia> Array{Number, 1} <: (Array{<:Number, 1})
true

```

This confused me at first too, but it’s just a matter of knowing what the syntax is really saying. I actually prefer the equivalent but more verbose syntax `Array{T, 1} where T <: Number` just to help myself tell the difference from `Array{Number, 1}`.

---

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [November 7, 2020, 6:44am UTC](https://discourse.julialang.org/t/argument-which-is-an-array-of-the-same-subtypes-dont-match-array-of-super-type/49712/8 "2020-11-07T06:44:39Z")

</div>

yay! I finally get it 😃

Thanks very much to everyone for helping me to understand !
