Topic: Proposal for user defined operaters.


Author: maxtal@extro.ucc.su.OZ.AU (Tim Lister)
Date: 7 May 92 15:01:32 GMT
Raw View
In article <643@manutius.UUCP> garyp@manutius.UUCP (Gary Powell) writes:
>
>I would like to add to the C++ language definition the notion of user defined
>operators.  These would be defined with the same scoping rules as functions
>but would have user defined precedence. The names allowed would exclude all
>reserved  names, ie extern, delete etc.
>
>In order to specify precedence some sort of new keyword is required.  I
>propose:
>precedence level # {
>    declaration;
>};
>
>Where "#" is some integer between 0 and MAX_INTEGER.
>
>eg:
>class X {
>...
>public:
>    friend X& operator foo(type_specifer rhs,type_specifier lhs) { ... };
>    precidence level 10 { foo(type_specifer, type_specifier); };
>...
>};
>
>Where one could say,
>
>main ()
>{
>    X x, y, c;
>
>    // ... sort of initialization ...
>
>    c = x foo y;
>
>}
>
>Why?
>This would allow for writing operators for matrix math.  While they lack the
>cryptic notation of APL it would be easier to read than the current
>technique of bending automic types to fit.  Allowing only declarators of the
>same rules as fns would prevent creating code no one could read.  Or at
>least no worse than the current mess.
>
>Problems:
>Precedence order rules could create a mess for inexperienced programmers.

 I think this proposal is in between
 1) Add operators with fixed (not user defined) precedence
    and associativity
 and
 2) Allow full grammar productions to be specified.
and has the disadvantages of both.

 As alternatives (also fishing expedition)
 1) Add a fixed set of new operators with predefined
    precedence and associativity.
 2) Allow a special form for user defined operators,
    but fix the precedence to equal + (or *) for binary
    ops and say + for unary.

 I like the idea of
 \div
 \subseteq
 \cup

 since these also have predefined typeset form
 (as used in TEX and AMSTEX)

 In fact, you could have

 \div      binds tightly
 \Div      same operator, looser binding
 \DIV      and again with very loose binding

 All operators would be left to right.

 The advantages of such a scheme are

 1) Typset form available via TEX
 2) Fixed format requires minimum changes to the lexical
    analyser---it can still be a DFA
 3) Minimum changes to the parser.
 4) Unlimited user operators available, and they could
    be overloaded too.
 5) Guarranteed NOT to interact with the standard types
 6) We still need a couple of other predefined specials
    such as ** or @ for power.

 John Skaller

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;-----------------------------------------------------------------------




Author: jimad@microsoft.com (Jim ADCOCK)
Date: 09 May 92 02:32:24 GMT
Raw View
In article <1992May6.183001.4817@sunb10.cs.uiuc.edu> pjl@sunb4.cs.uiuc.edu (Paul Lucas) writes:
|In <643@manutius.UUCP> garyp@manutius.UUCP (Gary Powell) writes:
|>This would allow for writing operators for matrix math.  While they lack the
|>cryptic notation of APL it would be easier to read than the current
|>technique of bending automic types to fit.  Allowing only declarators of the
|>same rules as fns would prevent creating code no one could read.  Or at
|>least no worse than the current mess.
|
| Use good ol' function notation; this, everyone understands.

I disagree.  On the contrary the use of functional notation in a wide
variety of numerical work results in incomprehensible code.  The
use of 1) ASCII and 2) Functional notation simply represents
the self-centricity of some programming communitities represented
primarily by Europeans and more specifically EuroAmericans who are
doing operating systems work.  ASCII and functional notation sucks
for solving a lot of real-world problems.  As a counterexample to
functional notation, consider the multipart notation of Smalltalk
and to a lesser degree Objective-C.  As a counterexample to ASCII
look to Unicode.  The programming world should be moving in a direction
that allows communities of programmers to express and solve *their*
particular problems in the language and notation suitable to *their*
needs.  Rather than insisting that everyone use the notation of EuroAmerican
OS developers.  What's the point of insisting that everyone use the
same notation?  In today's era of specialization you won't be able to
understand most of the problems other people are solving *anyway* !
Look at the writings about Galaxy to discover the strengths of being
able to express and solve problems in a symbology native to the problem.





Author: jimad@microsoft.com (Jim ADCOCK)
Date: 09 May 92 03:16:39 GMT
Raw View
In article <1992May6.220043.1320@taumet.com> steve@taumet.com (Steve Clamage) writes:
|The effect is to slow down compilation of all programs, even those
|which do not want to be able to define new operators.  A design
|philosophy of C++ is that a feature should have little or no cost
|for those who do not use it.

a) This sounds like an argument against trigraphs.

b) This sounds like an argument against cast-from-const.





Author: garry@ithaca.com (Garry Wiegand)
Date: Sun, 10 May 92 02:35:28 GMT
Raw View
I've always been of the opinion that languages that allow major
features like user-defined operators should do the job fully and
thoroughly. In particular, I feel that if you define an operator of
your own the symbol you use should be different from any already in
use in the language, for clarity and good coding style. C++ doesn't
yet allow this.

So I've never used a C++ user-defined operator ("overloaded
operator", in C++ terms), trivial cases like the complex number
operators aside. The feature as presently implemented is not useful
to me.


In a recent article steve@taumet.com (Steve Clamage) wrote:
>The effect is to slow down compilation of all programs, even those
>which do not want to be able to define new operators.  A design
>philosophy of C++ is that a feature should have little or no cost
>for those who do not use it.

A small comment: That design principle has been more important in
the past with respect to the run-time code than to the compiler
code. There are a whole lot of features in C++ that probably "make
the compiler slower". Even in the run-time the rule has sometimes
been honored in the breach - e.g., multiple inheritance.

In the case at hand, it ought to be straightforward to fix up the
lexical analyzer to handle user-defined operators. Those lexical
state tables aren't that complicated. (Fixing up the parser on the
fly does require a bit of sleigh-of-hand.)

Garry Wiegand --- garry@ithaca.com --- Ithaca Software, Alameda, California




Author: chip@tct.com (Chip Salzenberg)
Date: Mon, 11 May 1992 19:20:57 GMT
Raw View
According to ruprecht@informatik.uni-freiburg.de (Nick Ruprecht):
>Precedence:  Is "10" higher or lower than, say, multiplication?  You
>have to specify the precedence numbers for all the existing operators.

That's easy to solve: use strings and the collating order.  If you
want something between "a" and "b", call it "am".
--
Chip Salzenberg at Teltronics/TCT  <chip@tct.com>, <73717.366@compuserve.com>
      "Informix 4GL is not a 4G, and it's barely an L."  -- John Tombs




Author: moselecw@elec.canterbury.ac.nz (C.W. Moseley)
Date: 14 May 92 21:56:51 +1200
Raw View
That sounds a lot like BASIC line numbering strategey to me! Another hack to try to make a (dare I say it) poorly implemented idea function (sort of). Still, better than the `overloading' in something like SML (function language)

In article <2A0EC91A.7A06@tct.com>, chip@tct.com (Chip Salzenberg) writes:
> According to ruprecht@informatik.uni-freiburg.de (Nick Ruprecht):
> >Precedence:  Is "10" higher or lower than, say, multiplication?  You
> >have to specify the precedence numbers for all the existing operators.
>
> That's easy to solve: use strings and the collating order.  If you
> want something between "a" and "b", call it "am".




Author: garyp@manutius.UUCP (Gary Powell)
Date: 5 May 92 16:08:58 GMT
Raw View
I would like to add to the C++ language definition the notion of user defined
operators.  These would be defined with the same scoping rules as functions
but would have user defined precedence. The names allowed would exclude all
reserved  names, ie extern, delete etc.

In order to specify precedence some sort of new keyword is required.  I
propose:
precedence level # {
    declaration;
};

Where "#" is some integer between 0 and MAX_INTEGER.

eg:
class X {
...
public:
    friend X& operator foo(type_specifer rhs,type_specifier lhs) { ... };
    precidence level 10 { foo(type_specifer, type_specifier); };
...
};

Where one could say,

main ()
{
    X x, y, c;

    // ... sort of initialization ...

    c = x foo y;

}

Why?
This would allow for writing operators for matrix math.  While they lack the
cryptic notation of APL it would be easier to read than the current
technique of bending automic types to fit.  Allowing only declarators of the
same rules as fns would prevent creating code no one could read.  Or at
least no worse than the current mess.

Problems:
Precedence order rules could create a mess for inexperienced programmers.

Ie: current method.
   foo(x,foo(c,y));
      vs
   x foo ( c foo y );
      or
   x foo c foo y;


This is a fishing expedition.  I welcome comments, suggestions places to
put this proposal.

As usual, the ideas expressed here are mine and not necessarily those of
my employer.

Gary Powell ------------+ Internet: garyp@camco.aldus.com
c/o Aldus Corporation | uunet: manutius!garyp@uunet.uu.net
411 1st Ave South | uucp:  camco!manutius!garyp
Seattle, WA 98104  USA | Voice: (206) 622-5500




Author: checker@acf3.nyu.edu (Christopher Hecker)
Date: Wed, 6 May 1992 03:45:21 GMT
Raw View
>This would allow for writing operators for matrix math.  While they lack the
>cryptic notation of APL it would be easier to read than the current
>technique of bending automic types to fit.  Allowing only declarators of the
>same rules as fns would prevent creating code no one could read.  Or at
>least no worse than the current mess.

What kinds of operators would you define for matrix math?  In other
words, show me some code that you think would become more readable
with user defined operators.

Chris





Author: pjl@sunb4.cs.uiuc.edu (Paul Lucas)
Date: Wed, 6 May 1992 18:30:01 GMT
Raw View
In <643@manutius.UUCP> garyp@manutius.UUCP (Gary Powell) writes:

>I would like to add to the C++ language definition the notion of user defined
>operators.  These would be defined with the same scoping rules as functions
>but would have user defined precedence. The names allowed would exclude all
>reserved  names, ie extern, delete etc.

>In order to specify precedence some sort of new keyword is required.  I
>propose:
>precedence level # {
>    declaration;
>};

>Where "#" is some integer between 0 and MAX_INTEGER.

 What happens when a user #includes 2 classes written by two
 different authors who chose to use the same precedence level?

[ stuff deleted ]

>Why?
>This would allow for writing operators for matrix math.  While they lack the
>cryptic notation of APL it would be easier to read than the current
>technique of bending automic types to fit.  Allowing only declarators of the
>same rules as fns would prevent creating code no one could read.  Or at
>least no worse than the current mess.

 Use good ol' function notation; this, everyone understands.

>Problems:
>Precedence order rules could create a mess for inexperienced programmers.

 And experienced ones too.

>Ie: current method.
>   foo(x,foo(c,y));
>      vs
>   x foo ( c foo y );
>      or
>   x foo c foo y;

>This is a fishing expedition.  I welcome comments, suggestions places to
>put this proposal.

 Abandon it; it's not worth the added, nightmarish complexity
 for an isolated set of applications.  Not only do you have to
 specify precedence, but associativity.  Given "pow" as a raise-
 to-the-power-of operator:

   a pow b pow c
    = (a pow b) pow c
   or
    = a pow (b pow c)

 You can't say, "Whatever is more common"; Algol does it one way,
 Fortran, the other.

 Operator overloading, as it exists, was meant to naturally
 extend operators for appropriate types (like complex numbers,
 strings, ...).  It should not be used (abused) to make "clever"
 additions so that if you as a reader are in _just_ the right
 frame of mind, you'll "see" what the author meant.
--
 - Paul J. Lucas    University of Illinois
   AT&T Bell Laboratories  at Urbana-Champaign
   Naperville, IL   pjl@cs.uiuc.edu




Author: steve@taumet.com (Steve Clamage)
Date: Wed, 6 May 1992 22:00:43 GMT
Raw View
garyp@manutius.UUCP (Gary Powell) writes:

>I would like to add to the C++ language definition the notion of user defined
>operators.  These would be defined with the same scoping rules as functions
>but would have user defined precedence. The names allowed would exclude all
>reserved  names, ie extern, delete etc.

>In order to specify precedence some sort of new keyword is required.  I
>propose:
>precedence level # {
>    declaration;
>};

>Where "#" is some integer between 0 and MAX_INTEGER.

>eg:
>class X {
>...
>public:
>    friend X& operator foo(type_specifer rhs,type_specifier lhs) { ... };
>    precidence level 10 { foo(type_specifer, type_specifier); };
>...
>};

This gets proposed from time to time, and the ARM explains why it is
not currently in the language.  (Algol-68 allows this sort of thing.
The method used in that language, and its consequences, should
probably be studied by anyone making this proposal.)

Here are some of the points which need to be addressed in such a proposal.

Precedence:  Is "10" higher or lower than, say, multiplication?  You
have to specify the precedence numbers for all the existing operators.

Associativity:  This would also have to be specified.  Suppose I define
the symbol @ as an operator.  We have to say whether a@b@c is the
same as (a@b)@c or a@(b@c).  You will note that there are existing
operators with both left- and right-associativity, and the ability
to specifiy which is important.

Could I redefine precedence/associativity for an existing operator?
For example, suppose I want to use "^" as the exponentiation operator.
It needs to have a different precedence than the XOR operator.

Arity:  A new operator has some number of parameters.  How many?
Consider "*".  It can take either one or two parameters, depending
on whether it is the dereference or multiplication operator.  Do
you want to allow this kind of overloading?  Probably the arity
should be specified in the token definition, so that there is a
redunancy check when functions are defined.  For example, the "/"
operator is only binary.  It is an error to define operator/()
with one or three parameters, a useful redundancy check.

Do you want to be able to define trinary operators (like the
conditional-expression operator "?:")?  If so, how do you specify
the syntax for the parameters?  If trinary is OK, how about 4-ary,
5-ary, or N-ary?

Tokens:  What would be allowed as an operator symbol?  You have to
specify rules for making a new symbol.  Could I use "^", as in the
previous example?  How about "@", which is not a character in the
C++ source language?  How about "2compl" for 2's complement?  How
about something which looks like a partial token: "2'sCompl"?

Impact on implementations:  If you are allowed to define your own
tokens, this has a serious impact on compiler efficiency.  A
significant amount of compiler time is spent in lexical analysis
(scanning): dividing the source code into a sequence of tokens.
This is pretty fast because what constitutes a token is wired into
the language, but it still takes time.  If the compiler must be able
to react to compile-time token definitions, scanning will be much
slower.

Similarly, syntax analysis (parsing) is made more complicated and
slower.

The effect is to slow down compilation of all programs, even those
which do not want to be able to define new operators.  A design
philosophy of C++ is that a feature should have little or no cost
for those who do not use it.
--

Steve Clamage, TauMetric Corp, steve@taumet.com
Vice Chair, ANSI C++ Committee, X3J16




Author: steve@taumet.com (Steve Clamage)
Date: Thu, 7 May 1992 00:00:29 GMT
Raw View
I wrote:

>Precedence:  Is "10" higher or lower than, say, multiplication?  You
>have to specify the precedence numbers for all the existing operators.

It's actually worse than this.  Suppose multiplicative operators
have precedence 10 and additive operators have 9.  Now suppose I
want an operator to fit in between the two.  Should this be allowed?
If so, how about 2 operators with different precedences between
mult and add?  100 operators with different precedences?  This has
to be decided.
--

Steve Clamage, TauMetric Corp, steve@taumet.com
Vice Chair, ANSI C++ Committee, X3J16




Author: ruprecht@informatik.uni-freiburg.de (Nick Ruprecht)
Date: Thu, 7 May 92 08:34:17 GMT
Raw View
steve@taumet.com (Steve Clamage) writes:

>I wrote:

>>Precedence:  Is "10" higher or lower than, say, multiplication?  You
>>have to specify the precedence numbers for all the existing operators.

>It's actually worse than this.  Suppose multiplicative operators
>have precedence 10 and additive operators have 9.  Now suppose I
>want an operator to fit in between the two.  Should this be allowed?
>If so, how about 2 operators with different precedences between
>mult and add?  100 operators with different precedences?  This has
>to be decided.

The only way to specify precedence is relative to existing operators,
as in declarations of the form

 precedence = operators with equal precedence
 precedence > operators with lower precedence
 precedence < operators with higher precedence

The right side should contain a list of all operators this operator
can be mixed with in expressions. This way, the compiler could check
for inconsistencies.

BTW: I am all against the idea of adding operators to the language. It
is complicated enough as it is now.

--

Nick Ruprecht
Institut fuer Informatik der Universitaet Freiburg, Germany
(ruprecht@informatik.uni-freiburg.de)