[Python-Dev] More discussion on new infix operators

Huaiyu Zhu huaiyu_zhu@yahoo.com
Sat, 15 Jul 2000 13:30:31 -0700 (PDT)

I would like to redirect this discussion to deal with solvable problems,
rather than going on at several fronts, not all of them immediately
resolvable.  I'll provide some background, summarize what I've learned in
these discussions, and finally present some options and comments.

The issue arises from the attempt to introduce matrix operations into
python.  This may be an unfamiliar subject here, and we can't hope to agree
upon how fundamental or useful it is.  So let's just regard it as some
mysterious thing that engineers like to do [1].

It happens that in this domain the familiar arithmetic operators split into
two personalities, matrix-wise and element-wise.  Both are used frequently,
often within the same formula.  There are several successful commercial and
free languages for numerical computation. Many of them use the Matlab
approach: ordinary operators for matrix operation, dot-operators for
element-wise operation.  These languages are very elegant and powerful
within the domain of their applications.  The problem is, many of them are
not object oriented.  Most people do not use matrix as part of a math
course, but as a method for solving real problems.  So they are forced to
use Perl, shell scripts or embedded or embedding C/C++ to integrate these
calculations into their applications.

There is no need to explain here why people would want to use Python as the
glue language.  You may also agree that calling other languages within
Python cannot beat using native Python modules written in C.  A great deal
of work has been done to build the Numerical package.  Although the
situation improves tremendously, it still do not appeal to most users of the
dedicated matrix languages, for two reasons.  One is that NumPy emphasizes
on multi-array rather than matrix [2].  The other is the lack of support to
distinguish the two personalities of operators.

The MatPy project was started to solve these problems.  It defines matrix
classes that wrap around the Numeric classes, so that ordinary operators
default to matrix-wise operations, solving the first problem.  The second
problem cannot be solved without any change to Python syntax, because there
simply isn't enough binary operators available.  It is necessary to add new
operators.  They can all live in the area of current "invalid syntax" so
they would not interfere with existing code.  We made a patch to the parser
to add new operators, and I started a discussion on the best allocation of
these operators, when the discussion was also brought here.

So much for the background.  From these discussions I believe the following
is clear (please correct me).

1. It is not much more difficult to add .* style operators than to add @*
   style operators, even though . is overused and @ is unused.

2. There already exists some facilities for changing syntax within pure
   python.  But I don't remember any mention of where it is, and it seems
   people do not agree on its usability status at the moment.

3. Most here do not want additional operators in the core language until
   they see it successfully used in at least one domain.  There is also an
   argument that operators that are only meaningful in one domain would
   acquire completely incomprehensible semantics in all other domains.

4. There are three types of suggestion for matrix computation:

   1) Do not make any syntax change.  This includes two proposals:
      1.a) Use function calls like dotmul(a,b).  
	  1.b) Define Element and Matrix classes in parallel, with methods for
		   casting.  Use a.Element()*b.Element() in place of a.*b.

   2) Add additional operators.  These operators have fixed precedence as
	  their original counterparts but their semantics can be overridden in
	  applications.  They are encouraged to preserve the object-wise and
	  element-wise distinctions. 
	  2.a) Add @* type operators.
	  2.b) Add .* type operators.

   3) User a patched parser.  This also allows additional syntactic changes: 
	  3.a) Only as a temporary measure until it is accepted to core language.
	  3.b) Each application can have their own syntax with some marker on each
		   module to indicate which is which.
	  3.c) Just develop a different language.

5. Will introducing dot operators conflict with any existing language
   structures?  It does not affect member indicators, because that's always
   between two names.  It may interfere with a trailing decimal point, but
   that can be fixed by a simple rule (3.*a means 3. * a).

Now to the options with my own comments.

1.a) is unacceptable because infix operators improve readability
      tremendously compared with prefix operators.  

1.b) is unacceptable because it is too long and involves at least two method
      calls and object initialization for each operation.

2.a) was our original plan, and we have a patch for doing so.  It is less
      than optimal aesthetically, and we were not sure to use it for matrix
      or element-wise operations.  It is not intended to be submitted to the
      core language until the matrix package itself is ready to do so,
      although it couldn't possibly be changed at that time.

2.b) is my personal favorite.  As ESR pointed out, there are also potential
      applications in other areas.  To prevent incompatible semantics, it
      could be encouraged to be used only in "dual personality" situations.
      Whenever possible, the dot operators default to "element-wise
      operation" for any composite objects.  For example 
	  [1,2] + [10,20] == [1,2,10,20]	  
	  [1,2] .+ [10,20] == [11,22]

3) is not a good option in this case.  First, it is overkill.  Linear
   algebra is a very mature field and only a handful of well-known operators
   are called for.  These operations are written in science and engineering
   books for years and are very unlikely to change anytime soon.

   Second, it presents greater danger of incompatibility and fragmentation.
   Unlike different semantics, different syntax cannot even live within the
   same module.

   Third, the very reason people would want to use python for matrix
   computation is because it is an integral part of their application that
   need to work with everything else smoothly.

The situation now is that MatPy project has to move on, no matter what.  It
will introduce some kind of binary infix operators just to be viable (unless
some entirely new argument comes along).  But there do not seem to be
additional big hurdles on either algorithm or man power to impede its
further development.

I hope, and I do believe personally, that it will acquire wide-spread usage
once such basic facilities are provided, and will eventually be integrated
into the core language.  It would be next to impossible to change operators
at that moment.  Therefore I am most interested in hearing any thoughts on
whether there exist any mortal danger for introducing the dot operators.
For example, will it be confused with any planned new language features?
Arguments on whether this would open the floodgate for other feature
requests is unlikely to change the course of MatPy development because we
agreed not to talk about how specific the domain is [1].

That's all I could think of at this moment.   I'd like to thank your
patience for reading so far.  I am grateful for all the rational and very
helpful opinions I heard here, and I eagerly expect more.


[1] I'd be glad to provide easy introduction to numerical computation
	through email to anyone who would spend half an hour experimenting.

[2] The easiest (but not quite accurate) way to describe the difference is
    to compare with lists and strings: If you are doing text processing you
    want a dedicated string type, rather than a list of characters, although
    theoretically the latter can do just about everything the former can.