The problem, for me, with overloaded operators in something like C++ is that it frequently feels like an afterthought.
Doing "overloaded operators" in Lisp (CLOS + MOP) has much better "vibes" to me than doing overloaded operators in C++ or Scala.
Languages that get it right: SQL, Lua, ML, Perl, PHP, Visual Basic.
(NaN + 0.0) != 0.0 + NaN
Inf + -Inf != Inf
I suspect the algebraists would also be pissed if you took away their overloads for hypercomplex numbers and other exotic objects.
Unfortunately, many languages allow `string + int`, which is quite problematic. Java is to blame for some of this.
And C++ is even worse since literals are `const char[]` which decays to pointer.
Languages okay by my standard but not yours include: Python, Ruby.
Arithmetic addition and sequence concatenation are very very different.
——
Scala got this right as well (except strings, Java holdover)
Concatenation is ++
I guess forth as well... hmmm
It does: |
That character was put in ASCII specifically for concatenation in PL/1.
Then came C.
But C++ doesn't have that problem. Sure, a separate operator would have been cleaner (but | is already used for bitwise or) but I have never seen any bug that resulted from it and have never felt it to be an issue when writing code myself.
Granted this is probably a novice-level problem.
Sure, << for stream output is pretty unintuitive and silly. But what about pipes for function chaining/composition (many languages overload thus), or overriding call to do e.g. HTML element wrapping, or overriding * for matrices multiplied by simple ints/vectors?
Reasonable minds can and do differ about where the line is in many of those cases. And because of that variability of interpretation, we get extremely hard to understand code. As much as I have seen value in overloading at times, I’m forced to agree that it should probably not exist entirely.
Let's say I have matrices, and I've overloaded * for multiplying a matrix by a matrix, and a matrix by a vector, and a matrix by a number. And now I write
a = b * c;
If I'm trying to understand this as one of a series of steps of linear algebra that I'm trying to make sure are right, that is far more comprehensible than a = mat_mult(b,c);
because it uses math notation, and that's closer to the way linear algebra is written.But if I take the exact same line and try to understand exactly which functions get called, because I'm worried about numerical stability or performance or something, then the first approach hides the details and the second one is easier to understand.
This is always the way it goes with abstraction. Abstraction hides the details, so we can think at a higher level. And that's good, when you're trying to think at the higher level. When you're not, then abstraction just hides what you're really trying to understand.
The thing is code without operator overloading is also hard to understand because you might have this math thing (BigIntegers, Matrices) and you can't use standard notation.
Extremely clear at the "call site" what's going on.
The first two are already used for bitwise and logical or and the third isn't available in ASCII so I still think overloading + was a reasonable choice and doesn't cause any actual problems IME.