Discussion: new operators for numerical computation

John Lull lull at acm.org
Thu Jul 20 03:48:04 EDT 2000


(posted & mailed)


Huaiyu Zhu <huaiyu_zhu at yahoo.com> wrote:

> 1. What symbols to use.
> 
>    It seems that we can more or less concentrate on using either . or @
>    together with existing math operators.  Issues:
> 
>    (1) Use . or @

Either, except as noted below.

':' is another conceivable alternative.

As an aside -- @ is one of only 3 printing ASCII characters completely
unused in Python (along with $ and ?).  It seems to me a good thing to
leave a few such characters around for later use (though Unicode may
eventually make this consideration irrelevant).

>    (2) Which is matrixwise or elementwise

Either.  Which has the largest user base, NumPy or MatPy?  Which has
the widest applicability?  I presume the authors of both would be
willing to adopt whatever notation becomes the standard.

>    (3) Compatibility: NumPy uses * for elementwise, MatPy uses * for
>        matrixwise.

Either.  The authors of both *ought* to converge on one notation,
though admittedly that may involve a bit of pain for those using one
package or the other during the transition.  Perhaps a minor name
change at the same time is appropriate so that both old- & new-style
packages could be installed, & not break any existing code.

>    (4) Similarity with Matlab (but not really compatibility).

If matrixwise is the default, then I'd prefer dot notation simply
because it will be familiar to Matlab users.  If elementwise is the
default, I'd prefer a notation clearly distinct from Matlab's to avoid
confusion.

Another alternative would be to put the modifier *after* the standard
operator -- *. or *@ -- would this have any advantage for either
default?  Perhaps we should be considering .* vs. *@ ?

> 2. Precedence, scope and other properties:

>    - They have exactly the same properties as their ordinary counterparts.

Perfect.

> 3. Their behavior on other objects:
> 
>    Even though they are supposed to be used for numerical objects only, what
>    if user writes [10,20].+[1,2]?
> 
>    - Exception: no __dotadd__ or __rdotadd__ defined

Eminently reasonable.

>    - Behave as eadd and give [11,22]

List behavior is clearly different than matrix/array behavior.
Whatever you do, for some operators, lists are not going to behave as
a matrix/array user would expect.  Allowing them to be treated as
though they were arrays/matrices is (IMO) likely to lead to more
stupid mistakes, & will force people to learn which operators behave
properly & which don't.

What should happen when the user writes [10, '20'].+[1,2]?

>    - Behave as current + and give [10,20,1,2]

This just seems wrong.  It's a clearly different operator, intended to
have different results.  I see no reason anyone would either expect or
want this behavior.

> 4. The magic words:
> 
>    This really depends on issue 3 above.  
> 
>    - If it is intended that these thing should never acquire a meaning
>      outside numerical computation, they should be called __mmul__,
>      __emul__, etc, because that would describe the intension well.
> 
>    - If other classes, like UserList, are allowed to use them, it's better
>      to use __dotmul__, __atmul__, etc, so the association with the symbols
>      are strong.

I agree with your analysis, & have no strong preference.  I think it
really boils down to whether there are other domains for which these
operators make sense graphically.

>    - Someone mentioned __altmul__ for @*, meaning alternative mul.

That was me.  Frankly, I prefer any of the *other* alternatives.

> 5. Other bits and pieces:
> 
>    - How to deal with left division?
> 
>     (1) Use sol(a,b)

This I don't like.

>     (2) use /@ or /.

So element-wise left division might be ./@ ?  Yuck.

>     (3) use %

This makes the most sense to me.

>    - How to deal with power?  It is already two characters
> 
>     (1) Use ** and .** or @**

Not a problem for me.

>     (2) Steal ^ with .^ or @^ (not much chance, just mentioning here)

I don't like having one operator get modified differently.  

>    - Do we want a copy operator := which is different from =?  It allows
>      efficient code.  The following code does not change A
>          B := A
>          B += C
>      This definitely will be usable for other classes. Call it __copy__?

I'm not convinced this is terribly useful.  We can already write B =
A.copy(), and I don't see how the function notation is any substantial
disadvantage here.  I could be persuaded otherwise.

If it's to go in, your proposal will have to address issues of deep
vs. shallow copy for *when* (not if) it gets used in other domains.

>    - Since augmented assignment almost certainly will get in the core, we
>      need to consider combining them.  A few possible opinions
> 
>      (1) Just use prefix . or @ to mean e or m, use suffix = to mean in
>          place assignment, and all are well defined.

This I like -- consistency with the existing operators.

I could also live with it not working for any of the new operators, if
there's a reasonable explanation for not doing so.  Of course, my
definition of reasonable is probably different from yours.... :)

>      (2) a .**= 3 looks too long.  Don't combine them.

If augmented assignment works for some of the new operators, it ought
to work for all.  No special cases means no one has to *learn* the
special cases.

>      (3) allow .+=, etc but ban .**=.

Just because .**= is a bit long?


Another issue:
Your proposal needs to clearly indicate that __r*__() methods should
be invoked A/R just as they are for the existing operators.


BTW, I would like to second your nomination as the person to champion
this proposal.

Regards,
John



More information about the Python-list mailing list