# Is there a way to seamlessly inherit vector arithmetic on new types?

**URL:** <https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713>\
**Category:** General Usage\
**Created:** [January 16, 2019, 6:25pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713 "2019-01-16T18:25:01Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![philip](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/philip/32/17191_2.png) [@philip](https://discourse.julialang.org/u/philip)\
**Post date:** [January 16, 2019, 6:25pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/1 "2019-01-16T18:25:01Z")

</div>

I’m sure this is doable via macro by iterating through fields of a type, though I don’t have enough fluency with metaprogramming to know how to write this macro easily. But e.g. say I am going to be able to create a bunch of types.

```julia
struct Type1
    field1::Float64
    field2::Float64
end

struct Type2
    field1::Float64
    field2::Float64
    field3::Float64
end

```

I could manually do

```julia
import Base.*, Base.+, Base./
function *(x::Type1,r::Real)
   Type1(x.field1*r,x.field2*r)
end
function *(r::Real,x::Type1)
    x*r
end
function +(x::Type1,y::Type1)
    Type1(x.field1+y.field1,x.field2+y.field2)
end
function -(x::Type1,y::Type1)
   x + ((-1) * y)
end
function /(x::Type1,r::Real)
    x * 1/r
end
#etc. and again for Type2

```

But it seems there should be a one-liner way to just say “treat Type1 and its fields like a vector over Reals” and get all this for free. (Perhaps with NamedTuples?)

Thanks!

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [January 16, 2019, 6:27pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/2 "2019-01-16T18:27:44Z")

</div>

This sounds like a good fit for `StaticArrays.FieldVector`: [http://juliaarrays.github.io/StaticArrays.jl/stable/pages/api.html#FieldVector-1](http://juliaarrays.github.io/StaticArrays.jl/stable/pages/api.html#FieldVector-1).

---

<div class="post-metadata">

**Author:** ![philip](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/philip/32/17191_2.png) [@philip](https://discourse.julialang.org/u/philip)\
**Post date:** [January 16, 2019, 6:30pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/3 "2019-01-16T18:30:32Z")

</div>

Does look relevant, but seems like might be overkill and non-performant? I’ll give it a try; thanks!

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [January 16, 2019, 6:31pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/4 "2019-01-16T18:31:51Z")

</div>

It should actually be extremely performant (as in, it’ll generate the same or better code than the manual examples you coded up).

---

<div class="post-metadata">

**Author:** ![philip](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/philip/32/17191_2.png) [@philip](https://discourse.julialang.org/u/philip)\
**Post date:** [January 16, 2019, 6:33pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/5 "2019-01-16T18:33:35Z")

</div>

Cool 👍

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [January 16, 2019, 10:21pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/6 "2019-01-16T22:21:48Z")

</div>

Or just put an `SVector` inside your object instead of the 3 coordinates separately.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [January 17, 2019, 3:31am UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/7 "2019-01-17T03:31:35Z")

</div>

Alternatively to `StaticArrays.FieldVector`, you may use [https://github.com/JuliaDiffEq/LabelledArrays.jl](https://github.com/JuliaDiffEq/LabelledArrays.jl)

The differences for vector types are mostly minor, the big difference being that `StaticArrays.FieldVector` types are unique to your package, whereas the type of an `LabelledArrays.SLVector` is derived from the field names themselves.

The LabelledArrays package generalizes to matrices as well which is pretty cool.

Both FieldVector and SLVector are likely to be extremely efficient.

---

<div class="post-metadata">

**Author:** ![philip](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/philip/32/17191_2.png) [@philip](https://discourse.julialang.org/u/philip)\
**Post date:** [January 17, 2019, 5:07pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/8 "2019-01-17T17:07:30Z")

</div>

OK–I’ve tested this and indeed StaticArrays.FieldVector is equally as fast as the manual version I wrote, _and_ it plays nice with [GitHub - mauro3/Parameters.jl: Types with default field values, keyword constructors and (un-)pack macros](https://github.com/mauro3/Parameters.jl) for free.

Accordingly, I think this is a better solution (for me) than LabelledArrays just because I want to keep my custom types around rather than defining static LabelledArrays.

The only thing is, the FieldVector version seems to “forget” the original type in the computations (see below).

Any thoughts on whether this is doable while preserving the original type? I realize I can cast back after the fact; perhaps that’s the best option?

Thanks!

## Code:

```julia-auto
import Base.*, Base.+, Base.-, Base./

using Parameters
using StaticArrays
using BenchmarkTools

@with_kw struct TypeOnePlain
    field1::Float64
    field2::Float64
end

@with_kw struct TypeOneFV <: FieldVector{2,Float64}
    field1::Float64
    field2::Float64
end

function +(x::TypeOnePlain,y::TypeOnePlain)
    TypeOnePlain(x.field1+y.field1,x.field2+y.field2)
end
function *(x::TypeOnePlain,r::Real)
    TypeOnePlain(x.field1*r,x.field2*r)
end
function *(r::Real,x::TypeOnePlain)
    x*r
end
function -(x::TypeOnePlain,y::TypeOnePlain)
    x + ((-1) * y)
end
function /(x::TypeOnePlain,r::Real)
    x * (1/r)
end

x_plain = TypeOnePlain(field2=2,field1=1)
y_plain = TypeOnePlain(2,3)
r = 4.0

x_fv = TypeOneFV(field2=2,field1=1)
y_fv = TypeOneFV(2,3)

```

## Results:

```julia-auto

julia> @btime r * x_plain - y_plain / r
  67.119 ns (3 allocations: 96 bytes)
TypeOnePlain
  field1: Float64 3.5
  field2: Float64 7.25

julia> @btime r * x_fv - y_fv / r
  65.119 ns (3 allocations: 96 bytes)
2-element SArray{Tuple{2},Float64,1,2}:
 3.5
 7.25

julia> z_plain = r * x_plain - y_plain / r
TypeOnePlain
  field1: Float64 3.5
  field2: Float64 7.25

julia> typeof(z_plain)
TypeOnePlain

julia> z_fv = r * x_fv - y_fv / r
2-element SArray{Tuple{2},Float64,1,2}:
 3.5
 7.25

julia> typeof(z_fv)
SArray{Tuple{2},Float64,1,2}

julia> TypeOneFV(z_fv)
2-element TypeOneFV:
 3.5
 7.25

```

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [January 17, 2019, 7:19pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-seamlessly-inherit-vector-arithmetic-on-new-types/19713/9 "2019-01-17T19:19:34Z")

</div>

> [@philip](#):
>
> The only thing is, the FieldVector version seems to “forget” the original type in the computations (see below).

You can control this by overloading `StaticArrays.similar_type`. In this case:

```julia
StaticArrays.similar_type(::Type{TypeOneFV}, ::Type{Float64}, s::Size{(2,)}) = TypeOneFV

```

results in

```julia
julia> z_fv = r * x_fv - y_fv / r
2-element TypeOneFV:
 3.5
 7.25

```
