Many languages, especially those non-functional ones that originate from 20th century, have immutable syntax. Such symbols as +, (, or . have predefined meaning, which can't be changed by user.
Based on this, when you see a similar symbol, you think that its meaning is predefined by specification of the language. But it's not always true.
The most beautiful example of operator overloading in C++ is "lazy evaluation". Assume you defined a matrix class. You may want to use operator overloading to work with it, so you could write:
The expression at the right-hand side will be evaluated like this: first A*B will be computed and stored in some internal temporary variable tmp1, then (tmp1*C) will be computed, and stored in tmp2, etc.
However, it's known that evaluation of matrix multiplication chain can be optimized. So instead of straightforward definition where multiplying two matrices returns a matrix, we could define it in such a way that it returns a special "chain handler". This "handler" would accumulate references to all matrices involved in the multiplication, and perform the actual multiplication only once, when it gets converted to matrix M as a part of the assignment.
C++ is notorious for its operator overloading. You can imbue any meaning to (nearly) any operator used in expressions. This means, that any simple expression, such as "a = b + c" could actually invoke a complex user-defined procedure.
Of course, you can't redefine anything. Syntax elements used to define control-flow can't be redefined, as well as some operators that provide. And, most importantly, you can't create your own operators. But even with the powers you have, you can hide some userspace functions behind the usual syntax.
If you wrote or read Bash programs, you probably encountered such constructs:
The [...] "conditional" expressions are used to query file attributes and to compare strings. They are builtin shell operators...or not? Let's check:
pavel@lonely ~ $ ls -l "/usr/bin/[" -rwxr-xr-x 1 root root 35032 Jul 20 01:53 /usr/bin/[
What the hell? So these brackets are actually small programs that merely take the subsequent tokens as command-line arguments? Well, they could be:
pavel@lonely ~ $ "/usr/bin/[" -f /bin/bash ] && echo Yes Yes
Thankfully, Bash itself doesn't invoke them (it uses built-in implementation of this functionality). You can check it with strace or by temporarily removing this file. Perhaps, this file is kept for compatibility with other shells.
This example demonstrates that what you think of as syntax elements could actually be a user-defined function.
Haskell language has a special notation to make an arbitrary function infix. I.e. you could make an "operator" out of a simple function:
Prelude> min 1 2 1 Prelude> 1 `min` 2 1
However, another functional language, OCaml, doesn't have such syntax. It can define function as infix, but not "convert" it to infix as shown above. And there's no hope for it to work: it would require introducing additional syntax to language specification... would it?
# let ( /* ) x y = y x and ( */ ) x y = x y in 1 /*min*/ 2 ;; - : int = 1
The idea is to define some functions that look and feel like "syntax", leaving language definition intact. The above code defines infix functions named "/*" and "*/". And if you saw code like this (1 /*min*/ 2) at distance from the definition of these "functions", you would really thing it's some kind of OCaml syntax.
Here's the origin of this idea.
Modern languages give users more freedom to define and re-define meaning of what looks like syntax elements. This freedom can be used to write more beautiful and concise code, as shown in the examples above. By the way, do you know more?
Comments imported from the old website
Author Paul Shved
Modified November 7, 2010
License CC BY-SA 3.0