# Overloading arithmetic operators for custom types

**URL:** https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944
**Category:** New to Julia
**Tags:** question
**Created:** [October 14, 2023, 1:37am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944 "2023-10-14T01:37:24Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![evensong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evensong/32/202464_2.png) [@evensong](https://discourse.julialang.org/u/evensong)
#### Post date: [October 14, 2023, 1:37am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/1 "2023-10-14T01:37:24Z")

</div>

I’m doing doing exercises on [exercism.org](http://exercism.org) to get familiar with Julia (most of my experience is in Python, C++, or Java). For one exercise I’ve made a custom Clock type, and I want to overload Base.show to print a timestring field, and overload + and - to operate on the actual time value like so:

```julia
struct Clock{Time}
    time::Time
    timestring::AbstractString
    function Clock(hours::Int64, minutes::Int64)
    
        delta_hours = div(minutes, 60)
        delta_minutes = delta_hours * 60
        hours += delta_hours
        minutes -= delta_minutes
        
        if hours < 0
            hours %= 24
            hours += 24
        end
        
        if minutes < 0
            hours -= 1
            hours %= 24
            minutes += 60
        end
        
        minutes %= 60
        hours %= 24
    
        time = Time(Hour(hours), Minute(minutes))
        timestring = Dates.format(time, "HH:MM")
    end
end
    

Base.:(+)(c::Clock, m::Dates.Minute) = getfield(c, time) + m
Base.:(+)(c::Clock, h::Dates.Hour) = getfield(c, time) + h

Base.:(-)(c::Clock, m::Dates.Minute) = getfield(c, time) - m
Base.:(-)(c::Clock, h::Dates.Hour) = getfield(c, time) - h;

Base.:(-)(m::Dates.Minute, c::Clock) = m - getfield(c, time) + m
Base.:(-)(h::Dates.Hour, c::Clock) = m - getfield(c, time) + h

Base.show(io::IO, c::Clock{Time}) = print(io, timestring)

```

As far as I can tell from the docs, this should do what I’m wanting, but when I attempt, for example,

```julia
Clock(10, 0) + Dates.Minute(3) == Clock(10, 3)

```

I get the following error:

```julia
MethodError: no method matching +(::String, ::Dates.Minute)
Closest candidates are:
  +(::Any, ::Any, !Matched::Any, !Matched::Any...) at operators.jl:591
  +(!Matched::ExercismTestReports.Clock, ::Dates.Minute) at ./clock.jl:31
  +(!Matched::P, ::P) where P<:Dates.Period at /usr/local/julia/share/julia/stdlib/v1.8/Dates/src/periods.jl:77

```

This is exactly what I’m trying to address by overloading. Where am I going wrong?

Thanks in advance, and here is the stacktrace from exercism, in case it’s helpful:

````julia
Stacktrace:
 [1] macro expansion
   @ /usr/local/julia/share/julia/stdlib/v1.8/Test/src/Test.jl:464 [inlined]
 [2] macro expansion
   @ ./runtests.jl:69 [inlined]
 [3] macro expansion
   @ /usr/local/julia/share/julia/stdlib/v1.8/Test/src/Test.jl:1363 [inlined]
 [4] top-level scope
   @ ./runtests.jl:69```
````

---

<div class="post-metadata">

### Author: ![brianguenter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brianguenter/32/29519_2.png) [@brianguenter](https://discourse.julialang.org/u/brianguenter)
#### Post date: [October 14, 2023, 1:48am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/2 "2023-10-14T01:48:30Z")

</div>

it looks like your Clock function returns a string instead of a Clock object. You can use the new function to create a Clock object. Add something like this to the end of your function:

```julia
        time = Time(Hour(hours), Minute(minutes))
        timestring = Dates.format(time, "HH:MM")
        return new{Time}(time,timestring)
    end

```

---

<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: [October 14, 2023, 1:51am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/3 "2023-10-14T01:51:51Z")

</div>

`Time` is not an abstract type, so there is no need to parameterize that.

You are incorrect in thinking the fields are within the constructor’s local scope. They are not.

You can use a short hand notation for binary operators.

```julia
import Base: +, -
using Dates: Time, Hour, Minute

struct Clock{S}
    time::Time
    timestring::S
    function Clock(hours::Int64, minutes::Int64)
    
        delta_hours = div(minutes, 60)
        delta_minutes = delta_hours * 60
        hours += delta_hours
        minutes -= delta_minutes
        
        if hours < 0
            hours %= 24
            hours += 24
        end
        
        if minutes < 0
            hours -= 1
            hours %= 24
            minutes += 60
        end
        
        minutes %= 60
        hours %= 24
        time = Time(Hour(hours), Minute(minutes))
        return Clock(time)
    end
    function Clock(time::Time)       
        timestring = Dates.format(time, "HH:MM")
        return new{typeof(timestring)}(time, timestring)
    end
end

c::Clock + m::Minute = Clock(c.time + m)
c::Clock + h::Hour = Clock(c.time + h)
# Addition is commutative
t + c::Clock = c + t

c::Clock - m::Minute = Clock(c.time - m)
c::Clock - h::Hour = Clock(c.time - h)

Base.show(io::IO, ::MIME"text/plain", c::Clock) = print(io, c.timestring)

```

Here is a demo.

```julia
julia> c = Clock(4,5)                                                       
04:05

julia> c + Minute(5)                                                        
04:10  
                                                                                                                                                                                                                                                                                         
julia> c + Minute(5)                                                        
04:10   
                                                                                                                                              
julia> c + Hour(6)                                                          
10:05   
                                                                                                                                             
julia> Hour(7) + c                                                          
11:05      
                                                                                                                                         
julia> Minute(2) + c                                                        
04:07

```

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [October 14, 2023, 2:32am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/4 "2023-10-14T02:32:33Z")

</div>

> [@mkitti](#):
>
> You can use a short hand notation for binary operators.

> [@mkitti](#):
>
> `c::Clock + m::Minute = Clock(c.time + m)`

This is the most obscure and unintuitive way to define a function. For the sake of readability and understandability, I would not recommend that approach.

---

<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: [October 14, 2023, 2:34am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/5 "2023-10-14T02:34:51Z")

</div>

> [@evensong](#):
>
> `Base.:(+)(c::Clock, m::Minute) = ...`

Fair enough, but the above makes my eyes hurt.

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [October 14, 2023, 2:38am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/6 "2023-10-14T02:38:10Z")

</div>

Of course it comes down to a matter of taste, but the only unusual thing about `Base.:(+)(c::Clock, m::Minute) = ...` is the quoting of the function name.

---

<div class="post-metadata">

### Author: ![gvdr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gvdr/32/6387_2.png) [@gvdr](https://discourse.julialang.org/u/gvdr)
#### Post date: [October 14, 2023, 5:10am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/7 "2023-10-14T05:10:48Z")

</div>

> [@CameronBieganek](#):
>
> obscure and unintuitive

Do you mean because it is not immediately cleare that you are **defining** the behaviour of `+` there, or because the definition it’s not clear?

I must admit I actually like the way @mkitti wrote those lines. But maybe that’s because I’m still a mathematician before being a programmer 😆

---

<div class="post-metadata">

### Author: ![jondea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jondea/32/39086_2.png) [@jondea](https://discourse.julialang.org/u/jondea)
#### Post date: [October 14, 2023, 9:35am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/8 "2023-10-14T09:35:18Z")

</div>

That’s really cool, I didn’t know that you could define infix operators like that. I’d argue that it’s more intuitive to define an infix operator using infix notation. But it is definitely more obscure.

---

<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: [October 14, 2023, 9:44am UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/9 "2023-10-14T09:44:11Z")

</div>

It can also be a foot gun if you do not know what you are doing.

```julia-repl
julia> a + b = a                                                            
+ (generic function with 1 method)                                                                                                                      

julia> 3 + 4                                                                
3

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [October 14, 2023, 12:19pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/10 "2023-10-14T12:19:33Z")

</div>

It is a foot gun, but the problem isn’t really what happens when you _do_ want to define operations. Rather, the problem is when you are _not_ trying to do that, and end up doing it inadvertently.

Perhaps using this syntax will make you more aware of it, paradoxically reducing the risk of doing it in error.

The only way to remove the foot gun is to disallow the syntax.

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [October 14, 2023, 2:00pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/11 "2023-10-14T14:00:56Z")

</div>

> [@gvdr](#):
>
> Do you mean because it is not immediately cleare that you are **defining** the behaviour of `+` there, or because the definition it’s not clear?

Yeah, it doesn’t really look like a function definition. It looks like a typo:

```julia
julia> a = 1; b = 2;

julia> a - b == -1
true

julia> a + b = 3
+ (generic function with 1 method)

julia> # Oops, I just redefined addition.

julia> 10 + 20
3

```

But I guess the argument is that if we can define a non-infix function via `foo(x, y) = ...`, then we should be able to do the same with infix functions.

---

<div class="post-metadata">

### Author: ![evensong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evensong/32/202464_2.png) [@evensong](https://discourse.julialang.org/u/evensong)
#### Post date: [October 14, 2023, 3:35pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/12 "2023-10-14T15:35:32Z")

</div>

> [@mkitti](#):
>
> `Time` is not an abstract type, so there is no need to parameterize that.
> 
> You are incorrect in thinking the fields are within the constructor’s local scope. They are not.
> 
> You can use a short hand notation for binary operators.

Thanks for the quick response! That totally makes sense, it would need to return a clock object in order to get the string and the time.

is the ‘::MIME"text/plain"’ argument required, or is it just to give a nicer print? I thought from my reading of the show() docs that one could define a two argument show method without issues

---

<div class="post-metadata">

### Author: ![evensong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evensong/32/202464_2.png) [@evensong](https://discourse.julialang.org/u/evensong)
#### Post date: [October 14, 2023, 3:37pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/13 "2023-10-14T15:37:43Z")

</div>

> [@DNF](#):
>
> It is a foot gun, but the problem isn’t really what happens when you _do_ want to define operations. Rather, the problem is when you are _not_ trying to do that, and end up doing it inadvertently.
> 
> Perhaps using this syntax will make you more aware of it, paradoxically reducing the risk of doing it in error.
> 
> The only way to remove the foot gun is to disallow the syntax.

That’s actually what my thoughts were. Overloading basic arithmetic operators feels like dangerous territory to me, so I wanted to write it in a way that would make me think about exactly what I was doing. It probably is uglier, honestly, but I think it’s worth it when doing something so potentially risky.

---

<div class="post-metadata">

### Author: ![evensong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evensong/32/202464_2.png) [@evensong](https://discourse.julialang.org/u/evensong)
#### Post date: [October 14, 2023, 3:53pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/14 "2023-10-14T15:53:45Z")

</div>

> [@mkitti](#):
>
> ```julia
> c::Clock + m::Minute = Clock(c.time + m)
> c::Clock + h::Hour = Clock(c.time + h)
> # Addition is commutative
> t + c::Clock = c + t
> 
> ```

I would have thought it would only be commutative if you explicitly defined both ways–do all of the base operators for commutative arithmetic operations just automatically recognize commutative arguments?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [October 14, 2023, 5:56pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/15 "2023-10-14T17:56:51Z")

</div>

> [@evensong](#):
>
> is the ‘::MIME"text/plain"’ argument required, or is it just to give a nicer print?

No, if you only define a single `show` method it should be the 2-argument version. By default, the 3-argument version calls the 2-argument version.

You only ever define a 3-argument `::MIME"text/plain"` method for `show` in _addition_ to defining a 2-argument method, and only do so if you want a more verbose display for e.g. REPL output of a single value.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [October 14, 2023, 6:01pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/16 "2023-10-14T18:01:43Z")

</div>

> [@evensong](#):
>
> I would have thought it would only be commutative if you explicitly defined both ways

The code you’re quoting is doing exactly that. It defines the right-addition of `Clock` values in terms of the left-addition.

---

<div class="post-metadata">

### Author: ![mcmuffin6o](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@mcmuffin6o](https://discourse.julialang.org/u/mcmuffin6o)
#### Post date: [October 14, 2023, 6:53pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/17 "2023-10-14T18:53:24Z")

</div>

Good lord. This insidious mechanism should be removed from the language forthrightly, or at least be quarantined behind a feature flag.

KILL IT WITH FIRE BEFORE IT LAYS EGGS!

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [October 14, 2023, 7:04pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/18 "2023-10-14T19:04:00Z")

</div>

> [@evensong](#):
>
> Overloading basic arithmetic operators feels like dangerous territory to me

Overloading arithmetic is completely normal, and required to achieve basic functionality for many new types. Just don’t do it on someone else’s types, that’s type piracy.

The syntax for achieving it is a separate matter.

---

<div class="post-metadata">

### Author: ![gvdr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gvdr/32/6387_2.png) [@gvdr](https://discourse.julialang.org/u/gvdr)
#### Post date: [October 14, 2023, 8:18pm UTC](https://discourse.julialang.org/t/overloading-arithmetic-operators-for-custom-types/104944/19 "2023-10-14T20:18:05Z")

</div>

I mean, there IS a flag of sort, right? The overloading is not possible unless you import the base function you want to overload. And you would do it only with the intention of venturing into that “dangerous territory”.

And on the other hand, that syntax is amazing for people like me who gets into coding from other territories.

Let’s all try to be open minded 😸
