# Why do we need to define separate methods for commutative binary operators?

**URL:** <https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 25, 2020, 3:50pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044 "2020-06-25T15:50:40Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [June 25, 2020, 3:50pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/1 "2020-06-25T15:50:40Z")

</div>

Eg:

```julia
julia> struct abc
       x :: Int
       end

julia> Base.:(+)(a::abc, b::Int) = abc(a.x + b)

julia> abc(1) + 1
abc(2)

julia> 1 + abc(1)
ERROR: MethodError: no method matching +(::Int64, ::abc)

julia> Base.:(==)(a::abc, b::Int) = a.x == b

julia> abc(1) == 1
true

julia> 1 == abc(1)
false

```

Shouldn’t the second method in each case automatically be defined in terms of the first? This breaks commutativity in case of the equality. A missing method would have been better than this instead of a fallback.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [June 25, 2020, 3:58pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/2 "2020-06-25T15:58:35Z")

</div>

If your method is a subtype of Number and you define appropriate promote rules, you do not have to define both methods.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [June 25, 2020, 4:04pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/3 "2020-06-25T16:04:26Z")

</div>

I agree. I was using numbers as an example, and would have expected this to hold for arbitrary types.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [June 25, 2020, 4:07pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/4 "2020-06-25T16:07:09Z")

</div>

You could have a type where + is not commutative so defaulting to it being commutative would be strange.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [June 25, 2020, 4:34pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/5 "2020-06-25T16:34:18Z")

</div>

I think + is expected to be commutative, in fact this is one of the reasons oft repeated for not choosing it as the string concatenation operator.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [June 25, 2020, 4:39pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/6 "2020-06-25T16:39:24Z")

</div>

It’s expected to be, but that is just a norm. That stubborn isn’t coded into the language anywhere.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [June 25, 2020, 4:41pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/7 "2020-06-25T16:41:35Z")

</div>

Alright, but what about equality? Are there types that aren’t commutative under this operation?

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [June 25, 2020, 6:48pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/8 "2020-06-25T18:48:55Z")

</div>

The thing is that binary operators are just functions like all other functions, they are in no way special-cased in the language. Thus, they obey the same rules as all other functions. You could define == to be non commutative for your own type if you wanted to, because it’s just a regular function.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [June 25, 2020, 8:05pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/9 "2020-06-25T20:05:50Z")

</div>

I wonder if this was considered. There would have to be some way of marking some functions (or some symbols) as being commutative… and perhaps the extra complication was not thought worthwhile?

Mathematica does this:

```julia
Attributes[Plus]
{Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected}

Attributes[Dot]
{Flat, OneIdentity, Protected}

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [June 26, 2020, 12:00am UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/10 "2020-06-26T00:00:54Z")

</div>

It’d be _great_ if there is a way to encode some algebraic properties of binary operators like associativity and commutativity (and approximation of them)! IIUC Fortress uses it to let the compiler automatically parallelize reduction. A relevant RFC PR:

[https://github.com/JuliaLang/julia/pull/36424](https://github.com/JuliaLang/julia/pull/36424)

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [June 26, 2020, 12:07am UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/11 "2020-06-26T00:07:14Z")

</div>

> [@jishnub](#):
>
> I think + is expected to be commutative,

So I actually have an algebra pkg with non-commutative `+` operation, so `+` is not always commutative.

> **[GitHub - chakravala/Dendriform.jl: Dendriform di-algebra algorithms to...](https://github.com/chakravala/Dendriform.jl)**
>
> Dendriform di-algebra algorithms to compute using Loday's arithmetic on groves of planar binary trees - GitHub - chakravala/Dendriform.jl: Dendriform di-algebra algorithms to compute using Loda...

> [@mcabbott](#):
>
> There would have to be some way of marking some functions (or some symbols) as being commutative… and perhaps the extra complication was not thought worthwhile?

No, it would not be worthwhile. Methods should not have properties like this because multiple-dispatch would actually handle this type of issue in Julia already.

---

<div class="post-metadata">

**Author:** ![bradeneliason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bradeneliason/32/29031_2.png) [@bradeneliason](https://discourse.julialang.org/u/bradeneliason)\
**Post date:** [July 27, 2020, 5:37pm UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/12 "2020-07-27T17:37:21Z")

</div>

Instead of encoding algebraic properties on some functions, it might make sense to make a macro (e.g. `@commute`) which would define multiple methods in one line. For binary operators it’s doesn’t save very much space (i.e. one line vs two), but if there were methods with three or more inputs which all can be commuted, such a macro would cut the number of method definitions down a lot. Thoughts?

I think this would give you more control over what methods to make commutative or not. For example, you may want different methods for a custom type with a real number like `abc(1) + 1` and `1 + abc(1)` and other cases where you would want to commute the inputs. In particular, there are probably a lot of functions where a custom type with a `missing` should return a `missing` regardless of the order.

```julia
@commute Base.:(+)(a::abc, b::Missing) = missing

```

Encoding algebraic properties into functions could be beneficial if there are some performance optimizations that could occur from some algebraic manipulation. That seems like a lot of complexity to add to highly generalized functions. That being said, defining commuted methods with a macro could be a good first step to implementing such optimizations. Commutativity seems like an obvious property to add as a macro – I’m not as sure of other algebraic properties.

---

<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:** [July 28, 2020, 6:37am UTC](https://discourse.julialang.org/t/why-do-we-need-to-define-separate-methods-for-commutative-binary-operators/42044/13 "2020-07-28T06:37:07Z")

</div>

> [@bradeneliason](#):
>
> if there were methods with three or more inputs which all can be commuted, such a macro would cut the number of method definitions down a lot. Thoughts?

On the syntax level, the only multi-argument infix operators are `+`, `*`, and the ever-mysterious `++`. All other operators just take two arguments and do not chain in infix.

Also, multi-argument forms are only needed for non-associative operators, or if there is some efficiency advantage in doing things in one pass. Otherwise [folding](https://github.com/JuliaLang/julia/blob/9267bbf1fcd783278d820efa7e02e9357f962cc6/base/operators.jl#L533) works fine by falling back to the 2-argument case.
