Hi Doug,
At 2025-06-23T09:29:42-0400, Douglas McIlroy wrote:
Overloading
bit shifting operators to implement stream I/O was a
repellent choice
Without commenting on this judgement, I can tell how the convention
came about in a casual conversation.
I was perhaps the earliest serious experimenter with C++ overloading,
for a constructive solid geometry package in which arithmetic
operators were overloaded for matrices and vectors, and boolean
operators were overloaded for union and intersection of geometric
objects. I've forgotten how object subtraction (e.g. to drill a hole)
was represented. Sadly, the symbol vocabulary for overloading was
fixed, which meant that two vector products (dot and cross) vied for
one operator. Joe Condon put me onto an interesting analog of quotient
and remainder in 3D. The quotient. of two vectors, q=a/b is the ratio
of the projection of a onto b to b and the remainder r=a%b is the
component of a perpendicular to b, The usual quotient-remainder
formula holds::a = q*b + r.
Thanks for throwing considerable light on what prompted my heat.
I think your point about the overloadable symbol vocabulary being fixed
is a salient one, and puts a burden on overloading from a language
design and readability perspective that might not be sustainable.
However, I may be biased...while I'm accepting of function overloading,
I've never seen an implementation of operator overloading that pleased
me. I tell myself it's because I just haven't met the right language
yet, and that once I do I can thus claim an objective stance, but maybe
I'm just personally allergic to operator overloading. I already think
it's a bad idea to have "/" represent both integer and floating-point
division, and just within the past week we fixed a groff bug--that I
introduced--arising from the ambiguity.[1] (You guessed it--Ada doesn't
do this.)
If I were doing what Warren's done and devising my own riff on C, then
apart from stealing shamelessly from Ada, I'd use keywords for all
integer math operations: "add", "sub", "mul",
"div", "mod" (and maybe
Ada's "rem", too). To any C jockeys inclined to whine, I'd point out
that these are strongly reminiscent of the assembly language mnemonics
into which the operations will translate anyway, which _should_
harmonize with their mantra that they program "close to the metal".
That would reserve the arithmetic operator symbols for floating-point
operations, which is good because it's familiar from handheld
calculators (or, to update my superannuated notions, calculator apps
on handheld phones).
Your story about needing to assign distinct operators to two different
sorts of "product" is, I think, a strong one against operator
overloading. When programming we must cope with sundry varieties of
mathematical structures. I remember being intrigued when I learned that
the inner product (dot product) generalizes to a wide variety of
spaces[2] but the cross product does not. The cross product is
meaningful only in a 3-space. (Maybe one with an orthonormal basis to
boot; I haven't thought about this stuff in 10+ years.)
It seems that a lot of what we call "mathematical maturity" amounts to
awareness that much of what we were taught to assume as true in primary
or secondary school, or even most of an undergraduate program outside
the math department, was a fib.[3]
In that sense, we have Bolyai and Lobachevsky, and later Gödel, among
other celebrated thinkers, to thank for maturing us.
Once, while discussing some detail of overloading,
Bjarne remarked
that he'd like to find an attractive notation for stream IO, which
printf certainly is not. << and >> immediately popped into my mind.
They've been in the language ever since.
Oh, no! I have you to blame? :-O
Almost anything looks better than printf (anything but Fortran's
"FORMAT"), and that may have been unfortunate.
Equally casually, there was no discussion about the
set of operator
symbols, so C++ did not come up with a convention for symbol syntax,
such as that of Haskell.
I won't claim expertise with Haskell (I've yet to use it in anger), but
what exposure I've had to it suggests a carefully thought out language.
Our profession seems reluctant to accept new languages with that
property. We prefer JavaScript and PHP. :-|
Regards,
Branden
[1]
https://lists.gnu.org/archive/html/groff-commit/2025-06/msg00110.html
[2] "inner product spaces", natch ;-)
[3] One reason I'm so enthusiastic about linear algebra as a subject--I
think we should teach it to everyone, not even joking--is that
delivers a lot of benefit to one's critical thinking even as its
prerequisites are modest; all you really need is introductory
algebra and none of its weirder topics. With that small
armamentarium you can start learning how to reason about huge
classes of problems, and to do so in a "mature" way: that is, no
longer accepting models that are handed down on stone tablets, but
devising one's own, explicitly articulating one's assumptions,
seeing what properties result, and comparing them critically to the
phenomenon under study. You start with easy things like, "did I
select the correct number of (independent) variables to model this
problem?", and it gets more fun from there.
Recognizing when a problem _can't_ be modeled in a linear space is a
benefit that can't be overstated. But only familiarity with linear
algebra can equip you to make that judgment.