# Add Base operator function to custom struct automatically

**URL:** <https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008>\
**Category:** New to Julia\
**Created:** [June 19, 2022, 12:06pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008 "2022-06-19T12:06:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [June 19, 2022, 12:06pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/1 "2022-06-19T12:06:05Z")

</div>

I have a struct:

```julia
struct DF{T}
    index
    value::T
end

df=DF([:a,:b,:c],[1,2,3]);

```

When I need a add method to `DF` and `Vector`, I have to do this:

```julia
Base.:(+)(df::DF,x)=DF(df.index,df.value + x)

df + [1,2,3]

DF{Vector{Int64}}([:a, :b, :c], [2, 4, 6])

```

In a upcoming day, if I need a sub method, I have to add method:

```julia
Base.:(-)(df::DF,x)=DF(df.index,df.value - x)

```

Is there a way I can add a method to `DF`, then `DF` will have the `+ -...` methods automatically?

```julia
some_functions(df,DF,x)=DF(df.index,some_functions(df.value,x))

```

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [June 19, 2022, 1:07pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/2 "2022-06-19T13:07:22Z")

</div>

Well, in this case, you can write [macros](https://docs.julialang.org/en/v1/manual/metaprogramming/) yourself, e.g.

```nohighlight
julia> macro make(sym)
           return :(($sym)(df::DF, x)=DF(df.index, $(sym)(df.value, x)))
       end
@make (macro with 1 method)

julia> @make Base.:(+)

julia> DF([:a,:b,:c],[1,2,3]) + [1,2,3]
DF{Vector{Int64}}([:a, :b, :c], [2, 4, 6])

```

This makes it simple enough to create new functions.

If you want, you may wrap another macro to create `+-*/...` functions with one single call, that’s up to you.

---

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [June 19, 2022, 3:27pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/3 "2022-06-19T15:27:19Z")

</div>

Thanks for you help. `macro` method you mentioned is fine, but there must be some more simpy method. I found it in pakage `AxisArrays` [GitHub - JuliaArrays/AxisArrays.jl: Performant arrays where each dimension can have a named axis with values](https://github.com/JuliaArrays/AxisArrays.jl).

Here I can use the package like this:

```julia
> using AxisArrays

> v1=AxisArray([1,2,3],[:a,:b,:c])

1-dimensional AxisArray{Int64,1,...} with axes:
    :row, [:a, :b, :c]
And data, a 3-element Vector{Int64}:
 1
 2
 3

> v1 + [1,2,3]

3-element Vector{Int64}:
 2
 4
 6

> @which v1 + [1,2,3]
+(A::AbstractArray, B::AbstractArray) in Base at arraymath.jl:6

```

As you can see, when I call `v1 + [1,2,3]`, the add method worked in `v1.value` . I thought there must be a `+` method attaced to `Bae.:(+)(v::AxisArray,z::Vector)`, but when I call `@which v1 + [1,2,3]`, the result show that it derectively call the original `Base.+` rather than some custom added method. So I would guess the author of the package add some other more lower function to `AxisArray` struct.

---

<div class="post-metadata">

**Author:** ![Karthik-d-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karthik-d-k/32/35438_2.png) [@Karthik-d-k](https://discourse.julialang.org/u/Karthik-d-k)\
**Post date:** [June 19, 2022, 3:37pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/4 "2022-06-19T15:37:16Z")

</div>

> [@Brian1](#):
>
> ```julia
> > @which v1 + [1,2,3]
> +(A::AbstractArray, B::AbstractArray) in Base at arraymath.jl:6
> 
> ```

Here it falls back to `+` defined on `AbstractArray`, because `AxisArray` is subtyped based on `AbstractArray` as shown below (from [AxisArray impl](https://github.com/JuliaArrays/AxisArrays.jl/blob/master/src/core.jl))

```julia
struct AxisArray{T,N,D,Ax} <: AbstractArray{T,N}
    data::D # D <:AbstractArray, enforced in constructor to avoid dispatch bugs (https://github.com/JuliaLang/julia/issues/6383)
    axes::Ax # Ax<:NTuple{N, Axis}, but with specialized Axis{...} types
    AxisArray{T,N,D,Ax}(data::AbstractArray{T,N}, axs::Tuple{Vararg{Axis,N}}) where {T,N,D,Ax} = new{T,N,D,Ax}(data, axs)
end

```

So, it works if you also implement your type to be a subtype of `AbstractArray` ( **iff it is feasible in your case…!!** )

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [June 19, 2022, 3:42pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/5 "2022-06-19T15:42:04Z")

</div>

> [@Brian1](#):
>
> n `DF` will have the `+ -...` methods automatically?

this only makes sense if `DF <: Number`, and if this is the case (logically / in your mental model), then you can do:  
[https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#Promotion](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#Promotion)

because we have this defined:

> <https://github.com/JuliaLang/julia/blob/3efc725dbb2486a6fae91980d847b5bcaeb1ce67/base/promotion.jl#L388-L391>

---

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [June 19, 2022, 4:06pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/6 "2022-06-19T16:06:37Z")

</div>

Yes, this is exactly what I try to understand, Thanks very much.

---

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [June 19, 2022, 4:08pm UTC](https://discourse.julialang.org/t/add-base-operator-function-to-custom-struct-automatically/83008/7 "2022-06-19T16:08:16Z")

</div>

Yes, it makes sense only when `DF` isa `AbstratArray`. Thanks very much.
