# Overloading update operators

**URL:** https://discourse.julialang.org/t/overloading-update-operators/18771
**Category:** New to Julia
**Tags:** question
**Created:** [December 17, 2018, 10:36pm UTC](https://discourse.julialang.org/t/overloading-update-operators/18771 "2018-12-17T22:36:59Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![AmjadHD](https://avatars.discourse-cdn.com/v4/letter/a/3d9bf3/32.png) [@AmjadHD](https://discourse.julialang.org/u/AmjadHD)
#### Post date: [December 17, 2018, 10:36pm UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/1 "2018-12-17T22:36:59Z")

</div>

Hi all,  
I have this test code:

```julia
import Base.+

mutable struct Polynomial
    data::Dict{Int, Real}

    function Polynomial(data::Dict{Int, <:Real})
        @assert all(n->n>=0, keys(data))
        @assert all(!iszero, values(data))
        new(data)
    end
    Polynomial() = new(Dict())
end

function +(P::Polynomial, Q::Polynomial)
    """ P + Q """
    R = Polynomial()
    pds = keys(P.data)
    qds = keys(Q.data)

    for n in setdiff(pds, qds)
        R.data[n] = P.data[n]
    end

    for n in setdiff(qds, pds)
        R.data[n] = Q.data[n]
    end

    for n in pds ∩ qds
        if (c = P.data[n] + Q.data[n]) != 0
            R.data[n] = c
        end
    end
    R
end

function +=(P::Polynomial, Q::Polynomial)
    """ P += Q """
    pds = keys(P.data)
    qds = keys(Q.data)

    for n in setdiff(qds, pds)
        P.data[n] = Q.data[n]
    end

    for n in pds ∩ qds
        if (c = P.data[n] + Q.data[n]) != 0
            P.data[n] = c
        end
    end
end

```

I was trying to overload the += operator, but I had this error instead:

```julia
ERROR: LoadError: syntax: invalid identifier name "+="
Stacktrace:
 [1] include at .\boot.jl:317 [inlined]
 [2] include_relative(::Module, ::String) at .\loading.jl:1044
 [3] include(::Module, ::String) at .\sysimg.jl:29
 [4] exec_options(::Base.JLOptions) at .\client.jl:231
 [5] _start() at .\client.jl:425
in expression starting at C:\Users\User\Desktop\Tfach\julia_project\test.jl:36

```

how can I define the += operator ?

---

<div class="post-metadata">

### Author: ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)
#### Post date: [December 17, 2018, 11:13pm UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/2 "2018-12-17T23:13:52Z")

</div>

See [this section of the manual](https://docs.julialang.org/en/latest/manual/mathematical-operations/index.html#Updating-operators-1), specifically _writing `x += 3` is equivalent to writing `x = x + 3`_. In other words, you’d just overload `+`.

---

<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: [December 17, 2018, 11:24pm UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/3 "2018-12-17T23:24:11Z")

</div>

See also [https://github.com/JuliaLang/julia/issues/3217](https://github.com/JuliaLang/julia/issues/3217) and [https://github.com/JuliaLang/julia/issues/249](https://github.com/JuliaLang/julia/issues/249) for why we opted not to allow `+=` etcetera to be overloadable separately from `+`, unlike Python.

(For defining in-place operations, `.+=` is much more powerful because it fuses with other “dot” operations, and `.+=` can be customized via the broadcast machinery.)

---

<div class="post-metadata">

### Author: ![AmjadHD](https://avatars.discourse-cdn.com/v4/letter/a/3d9bf3/32.png) [@AmjadHD](https://discourse.julialang.org/u/AmjadHD)
#### Post date: [December 17, 2018, 11:36pm UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/4 "2018-12-17T23:36:37Z")

</div>

I don’t think `.+=` is suitable because here (and eventually in many other cases) the type is not a container (although might be seen as one), the required operation is on the type itself, not its elements.  
just a quick benchmark shows a speed and space gain between the two versions (Note: renamed `+=` =\> `iadd`):

```nohighlight
julia> using BenchmarkTools

julia> P = Polynomial(Dict(1=>2, 2=>-5))                                                                                                                                                                       
Polynomial(Dict{Int64,Real}(2=>-5,1=>2))                                                                                                                                                                       
                                                                                                                                                                                                               
julia> Q = Polynomial(Dict(0=>5, 1=>-2, 3=>5))                                                                                                                                                                 
Polynomial(Dict{Int64,Real}(0=>5,3=>5,1=>-2))

julia> @btime $P = $P + $Q                                                                                                                                                                                     
  2.941 μs (27 allocations: 2.70 KiB)                                                                                                                                                                          
Polynomial(Dict{Int64,Real}(0=>5,2=>-5,3=>5))                                                                                                                                                                  
                                                                                                                                                                                                               
julia> @btime iadd($P, $Q)                                                                                                                                                                                     
  1.829 μs (17 allocations: 1.08 KiB)

```

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [December 18, 2018, 8:02am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/5 "2018-12-18T08:02:05Z")

</div>

> [@AmjadHD](#):
>
> `data::Dict{Int, Real}`

Incidentally, perhaps you should make it `Dict{Int, T}` and `T` a type parameter, for performance. See [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/)

---

<div class="post-metadata">

### Author: ![AmjadHD](https://avatars.discourse-cdn.com/v4/letter/a/3d9bf3/32.png) [@AmjadHD](https://discourse.julialang.org/u/AmjadHD)
#### Post date: [December 18, 2018, 10:38am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/6 "2018-12-18T10:38:35Z")

</div>

yes but the Polynomial takes an arbitrary `Real`.  
changing the type to be more specific

```julia
mutable struct Polynomial{T<:Real}
    data::Dict{Int, T}

    function Polynomial(data::Dict{Int, <:Real})
        @assert all(n->n>=0, keys(data))
        @assert all(!iszero, values(data))
        new(data)
    end
    Polynomial() = new(Dict())
end

```

produces this error:

```julia
ERROR: LoadError: syntax: too few type parameters specified in "new{...}"
Stacktrace:
 [1] include at .\boot.jl:317 [inlined]
 [2] include_relative(::Module, ::String) at .\loading.jl:1044
 [3] include(::Module, ::String) at .\sysimg.jl:29
 [4] exec_options(::Base.JLOptions) at .\client.jl:231
 [5] _start() at .\client.jl:425
in expression starting at C:\Users\User\Desktop\Tfach\julia_project\test.jl:5

```

why is that ?

---

<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: [December 18, 2018, 11:18am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/7 "2018-12-18T11:18:30Z")

</div>

Excuse me for asking, but isn’t implementing polynomials using Dicts incredibly inefficient? It also seems to lead to _very_ messy code. Why not use tuples or StaticArrays to hold the coefficients? Or maybe just plain vectors would be the easiest.

---

<div class="post-metadata">

### Author: ![AmjadHD](https://avatars.discourse-cdn.com/v4/letter/a/3d9bf3/32.png) [@AmjadHD](https://discourse.julialang.org/u/AmjadHD)
#### Post date: [December 18, 2018, 11:30am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/8 "2018-12-18T11:30:33Z")

</div>

I don’t know if it’s “incredibly” inneficient, but it’s just for academic purpose, I have a python exercice to implement polynomials using dicts and i wanted to reimplement it as is in julia.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [December 18, 2018, 11:44am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/9 "2018-12-18T11:44:06Z")

</div>

> [@AmjadHD](#):
>
> why is that ?

Because your type is parametric and `new` needs that information:

```julia
mutable struct Polynomial{T <: Real}
    data::Dict{Int, T}

    function Polynomial(data::Dict{Int, W}) where {W <: Real}
        @assert all(n->n>=0, keys(data))
        @assert all(!iszero, values(data))
        new{W}(data)
    end
    Polynomial{T}() where {T <: Real} = new{T}(Dict{Int, T}())
    # and for a default of `Real`
    # Polynomial() = Polynomial{Real}()
end

```

EDIT: Note that the type assertion `T <: Real` in the constructors is redundant - it’s already ensured by the type signature itself and technically doesn’t need to be checked in the constructor again.

---

<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: [December 18, 2018, 11:44am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/10 "2018-12-18T11:44:23Z")

</div>

OK, that’s fine. It just seems so much more obvious to use vectors (or tuples) which have integer indices by default, than to use dicts. I guess it can be useful if you have very widely separated terms, like 2x^3 + 11x^{74} or something.

Python loves dicts, but in Julia they are not necessarily the obvious goto solution.

---

<div class="post-metadata">

### Author: ![AmjadHD](https://avatars.discourse-cdn.com/v4/letter/a/3d9bf3/32.png) [@AmjadHD](https://discourse.julialang.org/u/AmjadHD)
#### Post date: [December 18, 2018, 11:49am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/11 "2018-12-18T11:49:34Z")

</div>

Thanks, I just found out that examining the code in Polynomials.jl

---

<div class="post-metadata">

### Author: ![AmjadHD](https://avatars.discourse-cdn.com/v4/letter/a/3d9bf3/32.png) [@AmjadHD](https://discourse.julialang.org/u/AmjadHD)
#### Post date: [December 18, 2018, 11:54am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/12 "2018-12-18T11:54:14Z")

</div>

I guess dicts do have some advantage here in making sure the uniqueness of the degrees.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [December 18, 2018, 11:55am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/13 "2018-12-18T11:55:24Z")

</div>

> [@DNF](#):
>
> I guess it can be useful if you have very widely separated terms, like 2x3+11x742x^3 + 11x^{74} or something.

In that case, would a `SparseVector` be good as well? This would need some testing, but I’m feeling lucky today in saying it would be easier to use with existing multiplication etc.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [December 18, 2018, 11:57am UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/14 "2018-12-18T11:57:15Z")

</div>

The indices of the vector or tuple would be equivalent to the power at that position in the example by @DNF - for example, `v = [3 0 0 2 0]` would uniquely describe the polynomial 3x^4 + 2x.

---

<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: [December 18, 2018, 12:04pm UTC](https://discourse.julialang.org/t/overloading-update-operators/18771/15 "2018-12-18T12:04:31Z")

</div>

> [@AmjadHD](#):
>
> I guess dicts do have some advantage here in making sure the uniqueness of the degrees.

Not quite sure what you mean.

A quick and dirty test using vectors gave me a 60x speedup using vectors and 10-15th power polynomials, both for construction and addition. If you have only small polynomials, you can probably get incredible speedups with tuples/staticvectors, though at the cost of more messing about with type parameters and maybe generated functions.
