# Should + always be commutative?

From the manual:

While `*` may seem like a surprising choice to users of languages that provide `+` for string concatenation, this use of `*` has precedent in mathematics, particularly in abstract algebra.

In mathematics, `+` usually denotes a commutative operation, where the order of the operands does not matter. An example of this is matrix addition, where `A + B == B + A` for any matrices `A` and `B` that have the same shape. In contrast, `*` typically denotes a noncommutative operation, where the order of the operands does matter. An example of this is matrix multiplication, where in general `A * B != B * A` . As with matrix multiplication, string concatenation is noncommutative: `greet * whom != whom * greet` . As such, `*` is a more natural choice for an infix string concatenation operator, consistent with common mathematical use.

Sometimes I define my own operator methods. Should I use `+` only for commutative operations?

I think this will always be decided on a case by case basis. That said, itâ€™s hard to think of anything non-commutative that `+` would be an appropriate operator for. Do you have anything specific in mind?

For example, Iâ€™m thinking of declarative plotting tools that combine plot layers with `+`, like ggplot2 (in R) and AlgebraOfGraphics.jl in Julia. In ggplot, the order of the arguments determines the layer order (i.e. which goes on top).

Yes, I would tend to recommend `*` or some other operator, rather than `+`, for this, in keeping with the style of Base.

8 Likes

Thatâ€™s good to know. Are there other operator conventions that I can learn about?

(cc @piever in case you have thoughts on this)

In Gadfly, we use `push!`, discussion here

3 Likes

The one other thing I would consider is that in general, if you have both `+` and `*` defined, they probably should distribute with each other (ie `a*(b+c)=a*b+a*c`). Again, this isnâ€™t a hard requirement, but if you donâ€™t have a ring structure, you should at least think carefully before using `+` and `*`.

1 Like

Does floating-point arithmetic satisfy the distributive law? Intuitively I would think that not always.

No:

``````julia> 0.1 * (0.1 + 0.3)
0.04000000000000001

julia> (0.1 * 0.1) + (0.1 * 0.3)
0.04
``````
1 Like

Yeah floating point sucks . The good news is for floating point, I think you do actually get a good error bar where it will be equal up to 1 ULP.

1 Like

You heard it here first folks. `+(::AbstractFloat, ::AbstractFloat)` and `*(::AbstractFloat, ::AbstractFloat)` are now illegal.

8 Likes

In AlgebraOfGraphics, `+` and `*` are very close to forming a semiring structure (other than drawing order, I would say everything works, including distributivity), so I think the overloading is justified. One can always pass an explicit `z`-level to the layer to customize what is â€śdrawn on topâ€ť.

The `Base` way to implement it would be something like `vcat` (to combine lists of layers) and `kron` (to do all pairwise products of layers, which is currently done via `*`), but I think that makes the code less readable. I had initially though about using `âŠ•, âŠ—` (semiring up to isomorphism) but that was not considered particularly user-friendly or easy to type. I think thatâ€™s an important consideration for something like plotting, where you often just want to explore something quickly.

2 Likes