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.
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.
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
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.
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: