user-defined operators

Richard A. O'Keefe <>
Thu Apr 1 03:18:38 CEST 2004


I am now totally baffled:

Samuel Rivas <> wrote:
1 > As you stress, a symbol that can represent different
1 > operations in different contexts is said to be "overloaded".  +
1 > ++ and * are DIFFERENT operations, your definition says nothing
1 > about using the same function name to indicate those operations.

I replied:
2 > Nor does it say anything about the Arian controversy, bimetallism, or the
2 > interpretation of quantum mechanics.  Why should one little definition have
2 > to deal with quite irrelevant matters?

Now Samuel Rivas <> has replied to that:
3 > It should deal with function names if you want it to justify your
3 > assertion:
3 > 	
3 >	By the definition I use, a symbol which is bound to a single
3 >	definition is not overloaded, no matter how many types that definition 
3 >	applies to.
	 
I am really confused by this.
My assertion is "The definition of overloading I use is '...'."
That's a fact about me.  How could my definition of "the particular
kind of user-defined operator I propose for Erlang" have any possible
relevance to that?

The definition of overloading I use just *IS*
    "a symbol (whether operator symbol of function symbol) is
     overloaded if and only if it is bound to more than one
     operation definition".
The only way anyone could challenge that is by watching my behaviour
for a couple of weeks and seeing whether I really do use "overloaded"
that way.  

By that definition, C++ and Java have overloaded symbols (Java has
system-defined and user-defined overloaded method symbols and system-
defined but not user-defined operator symbols) and Haskell and Erlang
do not.  They just don't.  It really is beyond debate that *by THAT
definition*, they really don't.  I don't have to justify this; anyone
who doesn't believe it can check for themselves.

I'm not proposing to change that.  In this thread, I have nothing new
to say about Erlang functions.  It is quite unreasonable for someone to
demand that my proposal for user-defined operators should say something
about function names when I have already said over and over and over that
I have nothing new to say about them.

	> In Erlang, +, ++, and * are bound to different definitions.
	> There is no proposal in this or any other thread to change that.
	
	  Where did I write there is a proposal to change these operators?
	
When you said that introducing user-defined operators would mean that
you didn't know what operators (and you specifically mentioned + ++ *)
meant any more.

	> 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".
	
	  So, is your f(X,Y) when integer(X) ... overloaded or not? In your
	previous mail you said that is a *single* definition, which necessarily
	lead us to the fact that an operator bound to f is not overloaded.

How many times do I have to say it?

f/2 in that example has ONE definition.
It is a CONFUSING function but not an OVERLOADED function.
Erlang simply doesn't have any mechanism for overloading functions.

Therefore an operator `f` referring to f can no more be overloaded
than f can.

	> 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.
	
	  Agreed, that is not the point.
	
If it isn't the point, what the h*** WAS your point?

Erlang *with* user-defined operators will not have any problems
that Erlang *without* user-defined operators does not have right now.

If you agree with me, then you have no argument against user-defined
operators.  If you don't, then that *IS* precisely the point.

	> 	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,
	
	  This is meant everybody can assume +, *, ++, /, !, ... will do
	what are supposed to do.

AND THEY STILL CAN.

	I am not trying to say introducing user defined operators will
	change the meaning of these built-in operators but that you can
	find one operator that is not "universal" (and I trying to argue
	in favour of this will be not a good thing)

Do you mean "CAN find" or "CAN'T find"?  And what do you mean by
"universal"?  I am really having great trouble understanding this
paragraph.

	> 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, 
	
	  Perhaps "well defined" is not a good description. I meant "well
	known".
	
In that case, so what?  The proposal for user-defined operators
does not change the set of "well known" operators in any what whatsoever.

	> 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.)
	
	  I still don't know where I wrote that.
	
It is a reasonable inference from what you wrote:
(A) You were attacking user-defined operators as bad.
(B) Specifically, you were attacking them on the grounds of "overloading".
(C) You implied that the existing set of operators was OK.
But if acting differently for different argument types is bad,
and any existing operators act differently for different argument types,'
then the existing set of operators (leaving aside ++ which you said you
didn't like, although oddly enough ++ and -- do NOT have this property)
cannot be good.

	> "functions are bound to programmers skills"?  I can make no sense of this.
	> Perhaps that proves your point, whatever it is.
	
	  When you are reading a program written by someone you can't assume 
	all functions do what you suppose them to do.

Well, no.  You as reader have a responsibility to read the internal
documentation.  So what?  WHY SHOULD OPERATORS BE EXEMPT FROM THAT RULE?

	It is programmer responsibility to write his functions right.
	However you can assume what operators will do if the set of
	operators is defined by the language.
	
You should imagine me pounding the keyboard and screaming in
frustration here.

(1) When you are reading a program in any programming language,
    you cannot assume that all operators do what you suppose them to do.
    (For example, the arithmetic operations in Erlang do *not* treat
    floating-point numbers in a way that I regard as tolerable, let
    alone reasonable.  This came as a rather nasty surprise).
    You have the *SAME* obligation to read the documentation of
    built-in operators that you have for any other kind of symbol.

(2) Built-in operators are in NO WAY different from built-in function
    symbols.  When I'm using <math.h> in C, I have the *same* (I really
    do mean, according to the standardisers, *exactly* the same) right
    to trust the behaviour of pow() as I have to trust the behaviour
    of *, the fact that one is written in parenthesis-call form and the
    other in operator form is WHOLLY IRRELEVANT.  And I have the same
    obligation to read the documentation.

(3) This applies quite generally.  The things I have a right to trust
    are the BUILT-IN things, not the things that are invoked via some
    particular synyax.  I have the SAME right to trust aString.length()
    in Java that I have to trust aString+aString; both are equally
    built-in.  In Erlang, it isn't just the built-in OPERATORS that
    you get to use and trust, it's the built-in FUNCTIONS as well.
    There is no meaningful difference between ++ and length/1 here.

    The distinction you are making between operators and functions
    is not in fact the relevant distinction.

(4) What is relevant?  Well, we can split operations into several
    groups in several ways.

	{language-defined, in standard library, from others' code, own}
	x
	{familiar, unfamiliar}
	x
	{conforms to documentation, sort of does, doesn't}

    You are implying that if an operator is in the language definition,
    it is familiar and conforms to its documentation.  Neither of these
    is necessarily true:  Erlang has acquired several more operators since
    the Erlang book was published, so even an experienced Erlang programmer
    could find them unfamiliar, and there can be bugs anywhere.  (For
    example, I once had to work around a C compiler which implemented
    <= as >= for unsigned integers.  Strictly speaking, the compiler got
    it right, the assembler was the real culprit.)

    You are also implying that if a symbol is NOT a language-defined
    operator, then it isn't familiar and correct.  If that implication
    does not hold, you have no argument.  But it doesn't hold.
    printf() is not an operator in C, but there can be few C programmers
    who aren't familiar with it.  length() is not an operator in Erlang,
    but there can be few Erlang programmers who are not familiar with it.
    An Erlang programmer should become very nearly as familiar with the
    functions in Erlang's stdlib as with the built-in operators.

    For reading, what counts is
    (i) Can I tell what the operation *is*?  (legibility)
    (ii) Do I know what it means?	(familiarity)
    (iii) If I don't, how hard is it to find out?  (accessibility of docs)
    (iv) Does it actually do what it's supposed to? (correctness)

    Familiarity is the key here, not the form of syntax used.

	You can think reading an unknown operator is like reading an
	unknown function.  I will not argue against that, it is only a
	personal point of view.  I only want to point that, up to this
	moment, opening the set of operators will add more complexity to
	source code reading, and that can be worth doing it on not.
	
(5) In the proposal we are discussing, it is COMPLETELY OBVIOUS which
    operators are built in (they don't have backquotes) and which are
    not (they do).  Reading a use of an unknown operator really IS
    like reading a call of an unknown function, because it obviously
    ***IS*** a function call.  If you "will not argue against that",
    then you have no grounds whatsoever, I really mean *NONE*, for
    your claim that this will add complexity to source code reading.

    In the presence of user-defined operators:  anything that looks like
    a built-in operator has to *be* a built-in operator and is no less
    readable, anything with backquotes around it has to be a function
    call and is no less readable than any other function call (more so,
    in many cases).


	> 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
	
	If they are not better they are, at least, the same.

The () forms are quite clearly WORSE.
We could argue about the better match for mathematical notation,
we could argue about whether it is better for the words to be in
the order that you would really like to say them,
but it is not a matter of opinion that the operator forms have one
great virtue for decoding:  you don't have to count the commas.

In C or Lisp or Haskell, you don't have to count arguments to figure
out which function is involved; a function name consists solely of an
identifier.  But in Erlang it is not so.  An Erlang function name
consists of an identifier and an arity.  To determine which function
is involved in a call, you have to count the commas and add one.
f(A,B) and f(A,B,C) call unrelated functions.

When you see    A `f` B,  it can't possibly be a call to f/3.

	  Languages are designed with a certain operator precedence to avoid the
	ambiguity, because infix notation IS ambiguous.

Ah, now I understand your form of argument.
Every man is a cripple, because if he didn't have his legs, he would
be a cripple.
Every system of infix operators is ambiguous, because if it didn't
have its system of precedence, it would be ambiguous.

This is a particularly dishonest way to attack user-defined operators,
because in fact the proposal under consideration ISN'T ambiguous; for
any given construct containing user-defined operators, there is only
one possible way they can be read.

Note, by the way, that it is entirely possible to have a notational
system in which there are infix operators, but absolutely no ambiguity,
even in the absence of any precedence.  Anyone who wants to argue about
notational engineering should be familiar with such systems.

	  Yes, yes, my question was about the real meaning of /
	
Who knows what the real meaning of / is?  I was there responding to
a claim about the operators taught in school, and at least in my
generation, / was NOT the operator used for division in school.

	> I'm old enough to remember when 2/6 was half a crown,
	> feature of PL/I.)
	
	  Oh! What function is supposed to be / then? (just curious, again)
	
It's a punctuation mark:
    pounds/shillings/pence
    day/month/year

	I'm trying to set out my view, you can think I am a scaremonger
	if you want.  For me I'll keep thinking it's only I don't agree
	with you like you don't agree with me.

You are saying that user-defined operators will make things bad.
You have no sound arguments for it,
and you have no empirical evidence for it.
That's scaremongering.
I _have_ empirical evidence (Haskell and Prolog experience) that it
doesn't make things bad, and sound arguments that it _can't_ make
things worse.

That's more than just disagreement.

It may be that the majority of Erlang programmers have some kind of
visual defect (or, more plausibly, horribly bad fonts) which will make
it impossible for them to read tokens containing backquotes.  It may
be that their primary school teachers programmed them to get confused
when they see backquotes (I see the fnords!).  It may be that Erlang
programmers just aren't as intelligent as Prolog or Haskell or Algol 68
programmers.  So it's possible that empirical evidence could be found
discrediting `operators`.  But I have a high opinion of Erlang
programmers and of primary school teachers.




More information about the erlang-questions mailing list