# Confusion about type parameterization and method applicability

**URL:** <https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874>\
**Category:** General Usage\
**Created:** [September 27, 2022, 3:23pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874 "2022-09-27T15:23:02Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [September 27, 2022, 3:23pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/1 "2022-09-27T15:23:02Z")

</div>

I define the type

```julia
@kwdef mutable struct Tablet{T}
    id = nothing
    a::T
    # ...
end

```

My program mostly operates on Vectors of these. One thing I need to do is jusxtopose such vectors to make longer vectors. I overload `Base.+` for that:

```julia
function (Base.:+)(a::Tablet{Any}, b::Tablet{Any})::Vector{Tablet{Any}}
    [a, b]
end

function (Base.:+)(a::Tablet{Any}, v::Vector{Tablet{Any}})::Vector{Tablet{Any}}
    [a, v...]
end

function (Base.:+)(v::Vector{Tablet{Any}}, b::Tablet{Any})::Vector{Tablet{Any}}
    [v..., b]
end

function (Base.:+)(v1::Vector{Tablet{Any}}, 
                   v2::Vector{Tablet{Any}})::Vector{Tablet{Any}}
    [v1..., v2...]
end

```

I also overload `Base,:*` to repeat individual `Tablet`s and `Vectors` of `Tablet`s:

```julia
function (Base.:*)(repeat::Int, t::Tablet{Any})::Vector{Tablet{Any}}
    result = Vector{Tablet{Any}}()
    for i in 1:repeat
	push!(result, copy(t))
    end
    result
end

function (Base.:*)(repeat::Int, v::Vector{Tablet{Any}})::Vector{Tablet{Any}}
    result = Vector{Tablet{Any}}()
    for i in 1:repeat
	append!(result, copy.(v))
    end
    result
end

```

When I try to combine tablets though, I get errors:

```julia
let
	border_color =RGB(0.5, 0.5, 0.5)
	border1 = Tablet(
		a=border_color,
		b=border_color,
		c=border_color,
		d=border_color,
		threading=BackToFront())
	border1 + border1
end

```

```julia
MethodError: no method matching +(::Main.var"workspace#3".Tablet{ColorTypes.RGB{Float64}}, ::Main.var"workspace#3".Tablet{ColorTypes.RGB{Float64}})

Closest candidates are:

+(::Any, ::Any, !Matched::Any, !Matched::Any...) at operators.jl:591

top-level scope@Local: 9[inlined]

```

Why are my methods on `Tablet` not candidates?

Thanks.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 27, 2022, 3:53pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/2 "2022-09-27T15:53:01Z")

</div>

I guess is one case of type variance: [Vector{Int} \<: Vector{Real} is false??? · JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/stable/typevariance/)

---

<div class="post-metadata">

**Author:** ![JonasWickman](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@JonasWickman](https://discourse.julialang.org/u/JonasWickman)\
**Post date:** [September 27, 2022, 3:59pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/3 "2022-09-27T15:59:48Z")

</div>

Here is a start to get this working:

```julia
Base.@kwdef mutable struct Tablet{T}
    id::Union{Nothing,Int64} = nothing
    a::T
    # ...
end

function (Base.:+)(a::Tablet{T}, b::Tablet{T}) where T
    [a; b]
end

function (Base.:+)(a::Tablet{T}, v::Vector{Tablet{T}}) where T
    [a; v]
end

function (Base.:+)(v::Vector{Tablet{T}}, b::Tablet{T}) where T
    [v; b]
end

tablet_1 = Tablet{String}( a = "hello")

tablet_2 = tablet_1 + tablet_1

tablet_3 = tablet_2 + tablet_1

```

A few notes: `[a,b]` will create a vector where `a` is the first element and `b` the second, while `[a;b]` will concatenate along the first dimension. Annotating return types is usually not necessary. The `where T` annotation is telling julia that `T` can be any type, but that it should all be the same type (I couldn’t give you a more technical explanation, someone more savvy can step in). For performance reasons it’s a good idea to make sure your fields are all type annotated.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [September 27, 2022, 4:06pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/4 "2022-09-27T16:06:13Z")

</div>

> [@JonasWickman](#):
>
> The `where T` annotation is telling julia that `T` can be any type, but that it should all be the same type

To make it work for different types it can be written as:

```julia
julia> function (Base.:+)(a::Tablet{<:Any}, b::Tablet{<:Any})
           [a, b]
       end

julia> a=Tablet(1,1)
Tablet{Int64}(1, 1)

julia> b=Tablet(1,"two")
Tablet{String}(1, "two")

julia> a+b
2-element Vector{Tablet}:
 Tablet{Int64}(1, 1)
 Tablet{String}(1, "two")

```

---

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [September 27, 2022, 7:08pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/5 "2022-09-27T19:08:47Z")

</div>

I changed the Tablet arithmetic methods to use `;` rather than `,` as suggested by @JonasWickman, and to specialize on `Tablet{<:Any}` rather than `Tablet{Any}` as suggested by @oheil:  
I also specialize on `Vector{<:Tablet{<:Any}}` instead of `Vector{<:Tablet{Any}}` to avoid what I think is a contravariance issue.

```julia
function (Base.:+)(a::Tablet{<:Any}, b::Tablet{<:Any})
    [a; b]
end

function (Base.:+)(a::Tablet{<:Any}, v::Vector{<:Tablet{<:Any}})
    [a; v...]
end

function (Base.:+)(v::Vector{<:Tablet{<:Any}}, b::Tablet{<:Any})
    [v...; b]
end

function (Base.:+)(v1::Vector{<:Tablet{<:Any}}, v2::Vector{<:Tablet{<:Any}})
    [v1...; v2...]
end

function (Base.:*)(repeat::Int, t::Tablet{<:Any})
    result = Vector{Tablet{<:Any}}()
    for i in 1:repeat
	push!(result, copy(t))
    end
    result
end

function (Base.:*)(repeat::Int, v::Vector{<:Tablet{<:Any}})
    result = Vector{Tablet{<:Any}}()
    for i in 1:repeat
	append!(result, copy.(v))
    end
    result
end

```

I also bneeded to add a method for `+` with more than two arguments:

```julia
function (Base.:+)(v1::Vector{<:Tablet{<:Any}}, vs::Vector{<:Tablet{<:Any}}...)
    result = v1
    for v2 in vs
	result += v2
    end
    result
end

```

I guess there isn’t a more general method for this in case someone needs right-associative `+` for their types fopr some reason (an APL interpreter?).

Thanks for your help.

If anyone is curious what this is about, the code is in

> <https://github.com/MarkNahabedian/crafts/blob/main/tablet_weaving/gray_code_tablet_pattern.jl>

For the very patient who want to see the live notebook in Binder, the link is

> **[GitHub: fonsp/pluto-on-binder/v0.19.4](https://mybinder.org/v2/gh/fonsp/pluto-on-binder/v0.19.4?urlpath=pluto%2Fopen?url=https%253A%252F%252Fraw.githubusercontent.com%252FMarkNahabedian%252Fcrafts%252Fmain%252Ftablet_weaving%252Fgray_code_tablet_pattern.jl)**
>
> Click to run this interactive environment. From the Binder Project: Reproducible, sharable, interactive computing environments.

---

<div class="post-metadata">

**Author:** ![JonasWickman](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@JonasWickman](https://discourse.julialang.org/u/JonasWickman)\
**Post date:** [September 27, 2022, 7:36pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/6 "2022-09-27T19:36:15Z")

</div>

I think if you’re going for this level of generality you could simply define

```julia
function (Base.:+)(a::Tablet,b::Tablet)
    [a;b]
end

function (Base.:+)(v1::Vector{Tablet},v2::Vector{Tablet})
    [v1;v2]
end

```

Vectors that contain a multitude of types may not be as performant as single-typed vectors though. Depending on your use case this may or may not be important.

As far as I know, `Tablet == Tablet{<:Any}`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 27, 2022, 7:43pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/7 "2022-09-27T19:43:39Z")

</div>

> [@Mark\_Nahabedian](#):
>
> I guess there isn’t a more general method for this in case someone needs right-associative `+` for their types fopr some reason (an APL interpreter?)

You mean something like this?

```julia
julia> function sum(args::Vector{T}...) where T
           result = fill(zero(T), length(args[1]))
           for arg in args
               result .+= arg
           end
           return result
       end
sum (generic function with 1 method)

julia> sum([1,2],[1,2],[1,2])
2-element Vector{Int64}:
 3
 6

```

---

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [September 27, 2022, 8:21pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/8 "2022-09-27T20:21:49Z")

</div>

No, I mean `a + b + c + ...`.

That parses to a single call Expr expecting an n-ary method for `+`.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [September 27, 2022, 11:35pm UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/9 "2022-09-27T23:35:56Z")

</div>

Something like this?

```julia
function Base.(:+)(a::Tablet{<: Any}, b::Tablet{<:Any}, c::Table{<:Any}...)
    [a; b; c...]
end

```

---

<div class="post-metadata">

**Author:** ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)\
**Post date:** [September 28, 2022, 12:37am UTC](https://discourse.julialang.org/t/confusion-about-type-parameterization-and-method-applicability/87874/10 "2022-09-28T00:37:39Z")

</div>

Yup. That’d work.
