user-defined operators

Richard A. O'Keefe ok@REDACTED
Wed Mar 31 07:22:30 CEST 2004

I wrote:
	> By the definition I use, a symbol which is bound to a single definition
	> is not overloaded, no matter how many types that definition applies to.

Samuel Rivas <samuel@REDACTED> replied most confusingly:

	  As you stress, a symbol that can represent different
	operations in different contexts is said to be "overloaded".  +
	++ and * are DIFFERENT operations, your definition says nothing
	about using the same function name to indicate those operations.
Nor does it say anything about the Arian controversy, bimetallism, or the
interpretation of quantum mechanics.  Why should one little definition have
to deal with quite irrelevant matters?

In Erlang, +, ++, and * are bound to different definitions.
There is no proposal in this or any other thread to change that.

Erlang *already* permits the definition of a function which sometimes
calls one, sometimes calls the other, of those operations.  That function
is nevertheless itself still ONE "operation".

	  You are not adding more polymorphism or overloading, you are mapping
	the problems of functions to the operators.

So what?  What kind of mental deficiency could cause someone to have
NO trouble with functions that can do different things depending on what
their arguments are, but to suddenly fall all to pieces when it is an
operator that does this?

People seem to be arguing against user-defined operators on the grounds that
operators have some kind of unique sacred character that makes them different
from functions.  But in EXISTING Erlang this is not so.

	Currently you can have confusing functions, but the set of
	operators is well defined and (more or less) widely accepted (I
	really don't like the ++ operator since it's just the same as
	lists:concatenate and you have to know it because of
	optimisation issues).

I don't know what is meant by "widely accepted" here.  It is, of course,
accepted that the set of Erlang operators is what it is; since the
language was first defined there can hardly ever have been a single day
when it was widely accepted that it was what it should be.  Right at the
moment, Joe Armstrong has a proposal for an additional operator, !!,
which is *not* well defined, at least on my reading of his slides.  Once
upon a time Erlang didn't have andalso or orelse.  I myself am quite
unhappy with the definition of / in Erlang at the moment; if I am doing
floating-point arithmetic on an IEEE-conformant machine (which I am), I
want IEEE-conformant arithmetic, not some sort of bastardised hybrid, which
is what you get at the moment.  There has been some disagreement about
what (1 bsl 63) * 2 should mean.  (Not about what it DOES mean, but about
what it SHOULD mean.)

Anyone who wants to pretend that + and * in Erlang do one and only one
thing is living in fantasy land.  And you cannot use Erlang for long
without discovering that X!Y does different things depending on what X is.
(Related things, yes.  The same things, no.)

Anyone who wants to claim that the sky will fall because user-defined
operators will open up a can of worms that isn't *already* squirming
over the edges of the tackle box is, well, let's be charitable, reading
some other Erlang manual than the one I read.

To judge the basic honesty of this argument, recall that the proposal
in question is this:

    - the existing operators would remain with their present definitions
      EXACTLY (no changes at all)
    - no new operators of the present forms could be defined at all
      (anything that looks like a present Erlang operator *IS* a
      present Erlang operator with whatever properties one considers
      ideologically important)
    - the only new operators proposed are
      `id` Arg		=== id(Arg)
      Lhs `id` Rhs	=== id(Lhs, Rhs)
      where id can be any alphabetic atom or variable name, where it
      is directly and immediately obvious to the reader not only THAT
      a function call is involved but WHAT that call is.

If you believe (contrary to the facts) that X * Y has some sacred
property that f(X, Y) does not, then this proposal should leave you
satisfied, because it still *will* have.  Only X `f` Y will have
whatever properties are presently peculiar to f(X, Y).

	  IMO, you need the operators to represent some actions you cannot
	easily write in the language.

There are no such actions for which OPERATORS are needed.  Any such actions
can be defined using function call syntax, and MOST such actions in Erlang
are defined using function call syntax.  Lisp is proof that operator syntax
is not needed.

Note, by the way, the following actual example:
    10> F = {erlang,'+'}, F(1, 2).
    12> erlang:'+'(1, 2).
    13> erlang:'bsl'(1,63).
Or this module:
    -export([foo/2, bar/0, ugh/1]).

    foo(X, Y) -> erlang:'+'(X,Y).

    ugh(Receiver) -> erlang:'!'(Receiver, fred).

    bar() -> spawn(foo, ugh, [self()]), receive X -> X end.
where foo:bar() ==> fred.

We see that at least some existing Erlang operators behave like calls
to related functions in a module, so right now, operators as such are
NOT needed.  Even message sends can be done, right now, in existing
Erlang, without using anything other than ordinary function calls.

	With those operator and other functions
	you can write more functions. So functions are bound to programmers
	skills to do them readable.

"functions are bound to programmers skills"?  I can make no sense of this.
Perhaps that proves your point, whatever it is.

	Operators do not, unless you allow user defined operators.
	That's why I think you are introducing more
	confusing to the language.
"introducing more confusing" is certainly confusing, I grant you that.

But again, I am obliged to call this scaremongering.  It's like someone
saying that dentistry will always be too dangerous to carry out on people,
when there are millions of people walking around to prove the contrary.
I have used, and continue to use, several programming languages where there
are user-defined operators.  I've been using one of the for 25 years, and
one of the others has _had_ user-defined operators for quite as long (well,
if it looks like a duck and quacks like a duck I'll call it a duck even if
I'm told it should be called a binary selector).  In practice, these
operators do much good and little or no harm.

	Perhaps is a matter of taste, but I don't think the use of
	user-defined operators (neither alphabetic or non-alphanumeric)
	improve the readability of the code.

I must ask:  how much experience have you had with them?
Do you *REALLY* think that

	is_element(X, S)  union(S1, S2)   del_element(X, S)  match(X, P)

are better than

	X `in` S	  S1 `union` S2   S `without` X      X `matches` P

	Infix notation is ambiguous

This is simply untrue.  Infix notation in Erlang is not at all
ambiguous and adding user-defined operators would not make it ambiguous.

	and we only use it for historic reasons.

Again, this is quite untrue.  Mathematicians have been engaged in
notational engineering for a couple of centuries.  Programming language
designers have been engaged in fairly intense notational engineering for
about half a century.  We've had languages (like Lisp) where nothing is
an operator, languages (like APL) where everything is an operator,
languages (like Smalltalk) with things that technically aren't operators
but are in all but name, languages (like Java) with a fixed set of
operators, and languages (like Prolog, Haskell, Eiffel, and Algol 68) with
user-defined operators.  If the only reason were historic, we'd know that
by now, and a fifty year history of Lisp would have shown programmers the
error of their ways.  It hasn't.  We use operators because they work well.
Specification languages commonly allow outfix, distfix, and mixfix operators
as well as prefix, infix, and postfix ones.

	>     Not familiar from school:
	> 	* (should be x) / (should be -:-)
	  Why / should be -:-? (just curious)
I used  "x"  for U+00D7 MULTIPLICATION SIGN
   and "-:-" for U+00F7 DIVISION SIGN
because I still don't quite trust E-mail to deliver non-ASCII letters
unmangled.  I'm old enough to remember when 2/6 was half a crown,
not a third.  (Heck, I'm even old enough to remember the "Sterling"
feature of PL/I.)

There may perhaps be reasons not to support user-defined operators in
Erlang, and it would be good to hear them rather than scaremongering.

More information about the erlang-questions mailing list