New PEP for infix operator

226 views
Skip to first unread message

Aaron Meurer

unread,
Feb 25, 2014, 11:31:02 AM2/25/14
to sy...@googlegroups.com
Some people on this list might be interested in this. Some folks are
giving another shot at writing a PEP to add a new operator to Python
for matrix multiplication. The discussion is at
https://github.com/numpy/numpy/pull/4351.

Those of you who work with tensors may want to have a look as well.
There is talk to extending the operator to higher dimensional arrays,
but I feel that the discussion would be easier if it were formalized
into the language of tensor contractions.

Aaron Meurer
Message has been deleted

Sergey Kirpichev

unread,
Feb 25, 2014, 6:02:02 PM2/25/14
to sy...@googlegroups.com
On Tuesday, February 25, 2014 8:31:02 PM UTC+4, Aaron Meurer wrote:
Some people on this list might be interested in this. Some folks are
giving another shot at writing a PEP to add a new operator to Python
for matrix multiplication. The discussion is at
https://github.com/numpy/numpy/pull/4351.

Really bad idea.  It's better to have an ability to define arbitrary
infix operator (like Haskell, for example).

Christophe Bal

unread,
Feb 25, 2014, 6:49:16 PM2/25/14
to sympy-list

Hello.

Can you give a little example showing how to define an infix operator in Haskell ?

Christophe

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/21d80555-342e-4ae1-b7f0-9db077bc37f6%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Sergey Kirpichev

unread,
Feb 25, 2014, 7:02:06 PM2/25/14
to sy...@googlegroups.com

Aaron Meurer

unread,
Feb 25, 2014, 7:10:33 PM2/25/14
to sy...@googlegroups.com
Previous PEPs have tried this and failed. This PEP is an attempt at a
compromise that suits the community's needs but still has potential to
be accepted by the BDFL.

Aaron Meurer

Christophe Bal

unread,
Feb 26, 2014, 5:35:25 AM2/26/14
to sympy-list

I'm not sure but it seems that Ruby syntax can be a solution. Here is an example.

class matrix():
    ...
   def @(self, mat):
        ...

Instead of the method __add__(self, ...) , we could use the method +(self, ...).

The only change will be to manage dynamical infix lexer for the Python parser.

Christophe BAL

Sergey Kirpichev

unread,
Feb 26, 2014, 7:22:42 AM2/26/14
to sy...@googlegroups.com
On Wed, Feb 26, 2014 at 2:35 PM, Christophe Bal <proj...@gmail.com> wrote:
> I'm not sure but it seems that Ruby syntax can be a solution. Here is an
> example.

Ruby can't do this as flexible as Haskell. AFAIK, only few predefined
operators can be used.

> class matrix():
> ...
> def @(self, mat):
> ...
>
> Instead of the method __add__(self, ...) , we could use the method +(self,
> ...).

How about __radd__?

Joachim Durchholz

unread,
Feb 26, 2014, 7:57:03 AM2/26/14
to sy...@googlegroups.com
Am 26.02.2014 00:02, schrieb Sergey Kirpichev:
> On Tuesday, February 25, 2014 8:31:02 PM UTC+4, Aaron Meurer wrote:
>
> Really bad idea.

What's bad about it?

> It's better to have an ability to define arbitrary
> infix operator

In general, yes, but you definitely need to weigh it against several issues:

- Dealing with fixity, i.e. infix, prefix, postfix. We'd want all three
if we're to stick closely to mathematical notation.
- How much parenthesizing do you want? If you wish to allow prefix and
postfix operators at the same precedence level, things can get
ambiguous: if % is both prefix or postfix, % x % could be either
(% x) % or % (x %). This might be undesirable if the language has no
preexisting rule of that kind (ever additional rule means a steeper
learning curve).
- How do you distinguish between operators and functions?
- How do you keep precedence levels under control? In particular, how do
you make sure that programmers know what precedence levels apply if they
read code that makes heavy use of user-defined operators?

> (like Haskell, for example).

In Haskell, every function is a prefix operator (despite appearances,
there is no such thing as a multi-parameter function).
This simplifies syntax tremendously (semantics, too, but that's
irrelevant here), which means that arbitrary operators fit in easily.

Unfortunately, this isn't necessarily easy in other languages.

Given all these constraints and caveats, I find it hard to judge any
proposal as good idea or bad idea. You always have to look at the design
goals (which may or may not match SymPy's), and at the existing language.

Sergey B Kirpichev

unread,
Feb 26, 2014, 10:41:04 AM2/26/14
to sy...@googlegroups.com
On Wed, Feb 26, 2014 at 01:57:03PM +0100, Joachim Durchholz wrote:
> Am 26.02.2014 00:02, schrieb Sergey Kirpichev:
> >On Tuesday, February 25, 2014 8:31:02 PM UTC+4, Aaron Meurer wrote:
> >
> >Really bad idea.
>
> What's bad about it?

Because it turn python to be a DSL for numeric computations.

> > It's better to have an ability to define arbitrary
> >infix operator
>
> In general, yes, but you definitely need to weigh it against several issues:

Yes, and I think it's not new idea and it was discussed already
in mail threads for previous PEP.

Aaron Meurer

unread,
Feb 26, 2014, 2:49:47 PM2/26/14
to sy...@googlegroups.com
On Wed, Feb 26, 2014 at 9:41 AM, Sergey B Kirpichev
<skirp...@gmail.com> wrote:
> On Wed, Feb 26, 2014 at 01:57:03PM +0100, Joachim Durchholz wrote:
>> Am 26.02.2014 00:02, schrieb Sergey Kirpichev:
>> >On Tuesday, February 25, 2014 8:31:02 PM UTC+4, Aaron Meurer wrote:
>> >
>> >Really bad idea.
>>
>> What's bad about it?
>
> Because it turn python to be a DSL for numeric computations.

How is that a bad thing? Python is already used heavily for numeric
computations. Adding this one thing would simplify so much of that
code.

Aaron Meurer

>
>> > It's better to have an ability to define arbitrary
>> >infix operator
>>
>> In general, yes, but you definitely need to weigh it against several issues:
>
> Yes, and I think it's not new idea and it was discussed already
> in mail threads for previous PEP.
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/20140226154104.GA10731%40darkstar.order.hcn-strela.ru.

Matthew Rocklin

unread,
Feb 26, 2014, 3:05:31 PM2/26/14
to sy...@googlegroups.com
This seems like an odd forum for this conversation.  I wonder if there is a discussion on this topic that reaches more of the affected community.


Joachim Durchholz

unread,
Feb 26, 2014, 3:37:41 PM2/26/14
to sy...@googlegroups.com
Am 26.02.2014 21:05, schrieb Matthew Rocklin:
> This seems like an odd forum for this conversation. I wonder if there is a
> discussion on this topic that reaches more of the affected community.

The PEP proposes to introduce @ and @@ as new operators.
Extending the language with arbitrary operators is outside the PEP's
scope (for better or for worse), so it's not appropriate for Sergej's
issue anyway.

It may be that SymPy can make a push for that if we find a consensus, so
the discussion here does have merit.
(Unfortunately, the PEP doesn't clearly list the reasons why Sergej's
approach was thrown out. Maybe a writeup is in order.)

Aaron Meurer

unread,
Feb 26, 2014, 8:04:36 PM2/26/14
to sy...@googlegroups.com
Yes, it's on the pull request that I linked to. But note that there is
a lot of history with this idea, so you should probably educate
yourself before jumping right in and claiming you know how to make
Python a better place.

Aaron Meurer
> https://groups.google.com/d/msgid/sympy/CAJ8oX-EE_dfcDrAazxLyELo%2B829c%3DpsKo2tiPFqcpaL1B%2BM6ng%40mail.gmail.com.

Sergey Kirpichev

unread,
Feb 27, 2014, 7:59:43 AM2/27/14
to sy...@googlegroups.com

On Wednesday, February 26, 2014 11:49:47 PM UTC+4, Aaron Meurer wrote:
> Because it turn python to be a DSL for numeric computations.

How is that a bad thing? Python is already used heavily for numeric
computations.

It's good for this specific domain, but bad for the Python in general,
as it is not a DSL.

btw, here is a discussion of the possibility to have generic infix ops (the whole thread):
https://mail.python.org/pipermail/python-dev/2008-July/081509.html
and some arguments against matrix mul as well, e.g.:
https://mail.python.org/pipermail/python-dev/2008-July/081537.html

Joachim Durchholz

unread,
Feb 27, 2014, 12:45:46 PM2/27/14
to sy...@googlegroups.com
(a) The idea has been rejected by the BDFL, so the question is what the
reasons for that were and whether a new proposal can eliminate them.
(BTW it's entirely possible that the current PEP will be rejected as well.)

(b) There's the question of what we as SymPy might want out of Python's
operator system. What issues do we have, what's making our life
miserable? (I can guess there is, it would be nice to have the
established notations for bra and ket, for example.)

To raise our voice in that discussion, it would probably be a good idea
to answer (b) first.
We can probably also shed some light on the @ proponents' claim that
matrix multiplication is the one use case for which adding another
operator is a good idea - I guess we'd disagree, but we should bring
statistics. (From the perspective of SymPy, @ for matrix multiplication
is nonsensical anyway, we do well with * - do we?)

Alexey U. Gudchenko

unread,
Feb 27, 2014, 4:42:10 PM2/27/14
to sy...@googlegroups.com
Usually (in the one expression) we use only one type of the binary
operator for the multiplication.

And the example in the PEP also use only one operator '@' in some
context without mixing with '*' operator in this expression (for the
same class):

S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

Moreover, I can't imagine easy the example when two types of the binary
operators can be used simultaneously for the same class in one
expression (or even in one block of expressions).

If it is so, then it is possible maintain code and expressions to be
readable with the help of the switching of the context for this "*"
operator. Just use the python's dynamical polymorphism.

Example:

Suppose we have a class of the array (class M). See attachment for details.

And we want to use sometimes the elemente-wise product, or sometimes
Cauchy product.


And we want to write down expressions more readable for both cases

a = M([1, 2, 3])
b = M([5, 7, 11])
c = M([1, 2, 4])

Element wise product:

>>> a * b * c
[5, 28, 132]

Cauchy product:

# switch to cauchy_product
>>> M.mul_current = M.mul_cauchy_product

>>> a * b * c
[5, 27, 94]


We can do it by switching: M.mul_current = M.mul_cauchy_product

(It is possible to use class method if it have a few methods to be
switched: __rmul__, for example)

Disadvantage of this:

We can forget to switch '*' operator to the default behavior after
usage, or this situation may occur as the result of some exception.

But may be it is possible to combine switching with the "with .. as"
statement. (Some __enter__, __exit__ methods?)


Element wise product:
>>> a * b * c
[5, 28, 132]

Cauchy product:


>>> with M.use_cauhcy_product() as dummy:
>>> a * b * c
[5, 27, 94]



The last example is not implemented in the attachment. But I don't see
the big problems, expect that "with...as" statement usually uses for the
object's context, not classes.

As my opinion (conclusion) I don't think that PEP for '@' operator is
timely and not even convenient.

--
Alexey Gudchenko
PEP-@.py

Alan Bromborsky

unread,
Feb 27, 2014, 5:36:23 PM2/27/14
to sy...@googlegroups.com
What is wrong with operator overloading in classes and using parenthesis
where you have to due to the operator precedence in python. In the
multivector class I use -

+ addition
- subtraction
* geometric product
^ exterior (wedge) product
| interior (dot) product

additionally you have to use parenthesis anyway if the operator is not
associative (the, |, dot product is not associative).

Alexey U. Gudchenko

unread,
Feb 27, 2014, 7:06:05 PM2/27/14
to sy...@googlegroups.com
As I understand you mean examples of
https://github.com/sympy/sympy/tree/master/sympy/galgebra/ga.py
https://github.com/sympy/sympy/blob/master/sympy/galgebra/tests/test_ga.py

and examples of the processor from the string (without parenthesis) to
the expression
https://github.com/sympy/sympy/blob/master/sympy/galgebra/precedence.py


> additionally you have to use parenthesis anyway if the operator is not
> associative (the, |, dot product is not associative).
>

I see that many types of products are used simultaneously in one
expression, and it is needed indeed.
May be you want use more ones?

I agreed that in the complex cases the priority of operators, non
associativity is significant.
For operator precedence I can't say anything.
But do not mind to to use parenthesis. If '*' operator, __mul__ well
defined, and parenthesis are used, then constructor of the expression
tree work perfect. (if sympy/core/mul.py:Mul.flatten not reorder the
arguments)

I just don't see the necessity of the additional "@" operator for
numpy's examples with matrix multiplication.

They justify the use of the operator "@" so that the operator "*" is
busy for element-wise product somewhere outside of the current context.

https://github.com/njsmith/numpy/blob/matmul-pep/doc/neps/return-of-revenge-of-matmul-pep.rst

But in this case (only one type of product is used in some scope) this
problem solved by switching of "*" binary operator. Without introduction
of new "@" operator in Python.



--
Alexey Gudchenko

Aaron Meurer

unread,
Feb 27, 2014, 8:02:37 PM2/27/14
to sy...@googlegroups.com
There *is* this in NumPy (which is the main use-case for this PEP):
numpy.matrix. But it causes headaches for everyone who uses it.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/530FB132.8030506%40goodok.ru.

Joachim Durchholz

unread,
Feb 28, 2014, 4:17:28 AM2/28/14
to sy...@googlegroups.com
Am 27.02.2014 13:59, schrieb Sergey Kirpichev:
>
> btw, here is a discussion of the possibility to have generic infix ops (the
> whole thread):
> https://mail.python.org/pipermail/python-dev/2008-July/081509.html

I have finally gotten around to read the thread.

It's a waste to time to read that. Lots of ideas being idly discussed by
people who know little about language design and keep arguing from their
personal use cases - which is interesting but only half of the relevant
aspects, the other half is possible interaction with other language
features.

Joachim Durchholz

unread,
Feb 28, 2014, 4:24:49 AM2/28/14
to sy...@googlegroups.com
Am 25.02.2014 17:31, schrieb Aaron Meurer:
> Some people on this list might be interested in this. Some folks are
> giving another shot at writing a PEP to add a new operator to Python
> for matrix multiplication. The discussion is at
> https://github.com/numpy/numpy/pull/4351.

I think it's irrelevant to SymPy.
It's a proposal to add a predefined @ operator that does matrix
multiplication.
SymPy does not need it - our users haven't exactly been asking for that
specific operator.
SymPy isn't seriously affected by it either. If it should happen to be
accepted into the language, SymPy can easily support it as a synonym for
*, and that's it.

I share Sergey's view that Python should (and probably could) profit
more from user-defined operators.
However, I do not think that the introduction of @ would be a problem,
it would just be enother predefined operator, and Python being Python,
any mechanism for user-defined operators would allow people to redefine
standard operators in subclasses.
So that issue is orthogonal to the introduction of @.

Aaron Meurer

unread,
Mar 1, 2014, 1:49:03 PM3/1/14
to sy...@googlegroups.com
I mostly posted on this list because the author of the PEP wanted some
input from people with knowledge of tensor mathematics, so that the
parts about higher dimensional arrays could be spelled out with a bit
more rigour, and I know that there are a few people in this community
who work a lot with tensors.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/531055E1.9080507%40durchholz.org.

Ondřej Čertík

unread,
Mar 4, 2014, 2:15:53 PM3/4/14
to sympy
On Sat, Mar 1, 2014 at 11:49 AM, Aaron Meurer <asme...@gmail.com> wrote:
> I mostly posted on this list because the author of the PEP wanted some
> input from people with knowledge of tensor mathematics, so that the
> parts about higher dimensional arrays could be spelled out with a bit
> more rigour, and I know that there are a few people in this community
> who work a lot with tensors.

Definitely. I think it would be nice if Python had some operators for that.

But at the same time, I don't think this is such a big deal. In
Fortran or NumPy,
the standard is to use * for elementwise operations, and matmul() resp. dot()
for matrix operations. It works ok in my opinion.

Ondrej
Reply all
Reply to author
Forward
0 new messages