[Python-ideas] Fwd: [RFC] draft PEP: Dedicated infix operators for matrix multiplication and matrix power

Nathaniel Smith njs at pobox.com
Fri Mar 14 22:21:12 CET 2014

On Fri, Mar 14, 2014 at 5:53 PM, Guido van Rossum <guido at python.org> wrote:
> I have now read the PEP, and I think it's good. I think it's a waste of time
> to keep bikeshedding on the choice of operator -- @ is the best compromise.
> I do have a few specific notes:
> - Right associativity is not unheard of in Python. E.g. **. If you
>   think that for other reasons @ should be right associative, don't
>   let Python's tradition stop you. But then you need to decide which
>   of * and @ binds more tightly -- e.g. does a*b at c mean a*(b at c) or
>   (a*b)@c? And if you choose the latter, it follows that a at b*c means
>   a@(b*c) -- is that okay? (And similar examples exist for the other
>   choice.)

Like Robert I have the suspicion that the best option is to make @
right-associative and place it just above (more tightly binding) than
*. But I'll poll numpy-discussion and friends and see if anyone has
ideas for more objective measures.

> - Did you consider a duck-typing (is that the word?) attribute?
>   E.g. a*b is elementwise multiplication; a.M*b must be used for
>   matrix multiplication.  (Your use of .T as "transpose" made me think
>   of this.)  Of course the question is, can you get those packages
>   that currently use * for matrix multiply to comply? (I don't consider
>   this a serious counter-proposal. But you list a bunch of rejected
>   alternatives; this could be in that list.

This is an interesting suggestion! I think it hasn't received full
consideration before because the tangle between numpy.ndarray and
numpy.matrix means that the most obvious implementation for an
ndarray.M attribute would be to return a full-fledged numpy.matrix
object... and no-one wants to encourage proliferation of numpy.matrix
objects. But returning a tiny special-purpose class that only
implements __mul__ would avoid that objection. At that point it's
basically a nicer version of the "user-defined infix" '*dot*' operator
idea. It has similar problems with needing an unaesthetically magical
implementation, producing a proliferation of special classes (one
extra one for each array type), requiring an allocation on every call,
etc., but this might well be the next-best thing to a real operator.

All in all, I think we'd rather have a real operator, so if you're
happy to go with @ then I won't put lots of effort into finding
horrible problems that force us to reject .M ;-), but I'll certainly
add it to the PEP in any case.

> - Is @@ really necessary?  It seems you are adding it mostly because
>   it's cute and because of the parallel with **, not because it is
>   actually important enough to add new syntax.  And then later you use
>   it as an argument for @, which seems a bit circular.  Also, if we
>   were to make @ right-associative, the parallel with ** is already
>   imperfect.

@@ hasn't received as much attention as the rest of the proposal, so
I'll check in with numpy-discussion etc. on this as well. But my
personal feeling is +0 on @@ -- all else being equal, it's nicer to
have it than not. Is all else equal? Given the existence of @, the
increase in language complexity is small (or arguably negative, since
people who know *, **, @ may be surprised to find @@ missing, and have
to memorize its non-existence as an extra rule); the opportunity cost
is low (given the existence of @ I can't imagine we'll want to use the
token @@ for something else later); and @@ will be used in real life,
if not as often as @ itself -- 'vec @@ 2' for squared Euclidean length
probably won't be too uncommon, 'matrix @@ n' gets used for things
like simulating random walks on graphs or other markov chains, and the
'matrix @@ -1' notation will probably be a nice win for beginners and
other less-sophisticated programmers who just want to get some
computation done in a way that doesn't require them to keep a more
complicated mapping between math and code notation in their head or
caring about numerical details. I think of @@ being like, say, '%=' --
nothing one would ever add syntax for in isolation, but if designing
an overall system of operators then it makes more sense.

Probably in the end it just comes down to your aesthetic judgement
:-). Numeric folk will be fine either way.

(And I wouldn't consider @@ a *strong* argument for spelling '@' as
'@'; it's just mentioned in that section because there aren't really
*any* strong arguments for preferring one spelling versus another, we
have to make a decision, and so a weak argument is better than
nothing. Two useful operators for the complexity cost of one is a good
deal? :shrug: Obviously if @@ gets dropped I'll drop that bullet point
as well.)

> - For better counts of usages, perhaps Sourcegraph.com might help?  It
>   is a source code query engine that has a Python parser and (limited)
>   type inference built in (also separately available as pysonar on
>   github IIRC). To be clear, I don't need more numbers to be convinced.

Oo, that is shiny, thanks for the tip.

> Once we've decided on associativity and @@, I'm ready to accept.

Wonderful to hear! Thanks for giving this so much time and attention
(on no warning)!


Nathaniel J. Smith
Postdoctoral researcher - Informatics - University of Edinburgh

More information about the Python-ideas mailing list