... In FORTRAN the `**' operator means exponentiation, and binds more
tightly than multiplication and division but less tightly than
parentheses and function calls.
(And, if I recall correctly, is non-associative as well: A**B**C
is an error.)
But perhaps I'm abusing you needlessly and owe an apology;
you may be referring to the problems of adding user-defined
operators on the fly and at the programmer's whim. Those would
indeed be "enomous" problems!
Although these, too, have been solved (for some definition of
"solved" anyway) in other languages.
But perhaps we need not generalize
from a question about one obviously missing operator to the issue
of accommodating every conceivable (and ill-conceived) operator
a programmer's diseased mind can imagine. If you want APL, you
know where to find it. ;-)
It, I think, is worth noting that APL -- a language designed by a
mathematician -- avoids the whole operator binding ("precedence
and associativity") problem by defining it away. Operators are
handled strictly in textual order, right to left. For instance,
* 3 + 4 (iota) 7
is handled as:
iota 7: produces the vector 1 2 3 4 5 6 7
+ 4 [vector]: produces the vector 5 6 7 8 9 10 11
* 3 [vector]: produces the vector 15 18 21 24 27 30 33
Also, as I think someone else mentioned in this thread, APL provides
sort operators (grade-up, which sorts into ascending order, and
grade-down, which sorts into descending order).
If you write pure functions (or ignore possible control flow and
"global variable" problems due to errors), the difference between
"function" and "operator" is mere syntax. A good programmer should
be comfortable with all three of these:
(* 2 (+ 3 4)) # functions, e.g., Lisp
2 3 4 + * # RPN, e.g., PostScript, FORTH
2 * 3 + 4 # "conventional" infix
This does not mean you cannot *prefer* one form over another (even
Lisp programmers write fancy macros), but there is no significant
difference. The spelling does not matter as much as the semantics.
Note that, on some machines (V7-and-earlier SPARC for instance):
int i, j, result;
...
result = i * j;
compiles to a subroutine call ("call .mul"), rather than a multiply
instruction, and:
size_t size;
size = sizeof(i);
compiles to a simple assignment, despite "sizeof(i)"'s resemblance
to a call to a function.