On Fri, Mar 14, 2014 at 5:53 PM, Guido van Rossum <guido@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@c mean a*(b@c) or (a*b)@c? And if you choose the latter, it follows that a@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)! -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org