Here’s an example of what I’m trying to do:

``````struct MyStruct
x::Int
end

function Base.:+(s::MyStruct, a::Int)
MyStruct(s.x + a)
end

s1 = MyStruct(5)
s2 = s1 + 3

# ------ Everything above this line works ----------

# Attempting to create the following function produces:
#  ERROR: UndefVarError: += not defined
function Base.:+=(s::MyStruct, a::Int)
s.x + a
s
end

s1 += 1
``````

Wondering if this is possible. Seems that `+=` is treated differently than other operators. It can’t be found in REPL help.

``````help?> +=
search:

Couldn't find +=
``````

`x += y` is a synonym for `x = x + y` in Julia, so you can’t overload it.

1 Like

Thanks.
There are some situations where it would be nice to modify a struct in-place, rather than create a copy.
But for those situations, I guess I’ll just create a slightly less-elegant `add!` instead.

You could just do `s.x += 1`.

1 Like

The `MyStruct` example was a trivial MWE.
The real use case involves updating many (but not all) fields in less straightforward ways.

Edit:
The specific use case is to overload the `*=` for Factorization so you can multiply factorizations together.

``````julia> f1 = Primes.factor(25)
5^2

julia> f2 = Primes.factor(36)
2^2 * 3^2

# ---- Would like to add the below capabilities -------
julia> f1 *= f2
2^2 * 3^2 * 5^2

# Looks like I'll have to settle for
julia> mul!(f1, f2)
2^2 * 3^2 * 5^2
``````

`+=` or `*=` are not inplace operators (the LHS variable is assigned to and the object is not mutated). `.+=` and `.*=` are.

I assume .+= is not overloadable either.

Wouldn’t this be type piracy?

Edit: well, unless you plan to contribute this functionality to the package itself, I guess.

You could try this package

It aims at helping with mutation of immutable structs

1 Like

Would be good to fix this if anyone feels like patching the docs:

1 Like

For an in-place calculation of a `mutable struct` (which I’d also like) it would be good to have `+=!` as a method.

I assume .+= is not overloadable either.

Unfortunately not. For that kind of questions, use

``````julia> Meta.@lower a .+= b
:(\$(Expr(:thunk, CodeInfo(
1 ─ %1 = (Base.broadcasted)(+, a, b)
│   %2 = (Base.materialize!)(a, %1)
└──      return %2
))))
``````

So you would need to write a `materialize!` function that checks whether the dest is identical to one of the arguments of the broadcast, but you cannot dispatch on that.

`add!` or `mul!` is probably the way to go, with respect to naming.

1 Like

What about ⇷? It looks kind of like a combination `+`-assignment operator.

``````julia> mutable struct Foo{T}
a::T
end

julia> function (⇷)(a::Foo{T}, b::T) where {T}
a.a += b
end
⇷ (generic function with 1 method)

julia> a = Foo(3)
Foo{Int64}(3)

julia> a ⇷ 3
6

julia> a ⇷ 3
9

julia> a ⇷ 3
12

julia> a
Foo{Int64}(12)
``````

Type it with `\nvleftarrow` + TAB. It has an arrow’s precedence, which quick tests seems to suggest is lower than `+`/`-`. I think the prec-names variable lists operator types in order from lowest to highest:

``````(define prec-names '(prec-assignment
prec-pair prec-conditional prec-arrow prec-lazy-or prec-lazy-and prec-comparison
prec-pipe< prec-pipe> prec-colon prec-plus prec-times prec-rational prec-bitshift
prec-power prec-decl prec-dot))
``````

For reference, here are all the operators, and here are the unicode inputs and how to type them.