<div dir="ltr"><br><br>On Friday, March 14, 2014 7:46:11 PM UTC-5, Aaron Meurer wrote:<br><br>On Friday, March 14, 2014 4:21:12 PM UTC-5, Nathaniel Smith wrote:<br><blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir="ltr"><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>On Fri, Mar 14, 2014 at 5:53 PM, Guido van Rossum <<a>gu...@python.org</a>> wrote: <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> I have now read the PEP, and I think it's good. I think it's a waste of time <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> to keep bikeshedding on the choice of operator -- @ is the best compromise. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> I do have a few specific notes: <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> - Right associativity is not unheard of in Python. E.g. **. If you <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   think that for other reasons @ should be right associative, don't <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   let Python's tradition stop you. But then you need to decide which <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   of * and @ binds more tightly -- e.g. does a*b@c mean a*(b@c) or <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   (a*b)@c? And if you choose the latter, it follows that a@b*c means <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   a@(b*c) -- is that okay? (And similar examples exist for the other <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   choice.) <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Like Robert I have the suspicion that the best option is to make @ <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>right-associative and place it just above (more tightly binding) than <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>*. But I'll poll numpy-discussion and friends and see if anyone has <br>ideas for more objective measures.
<br></div></blockquote><br>I guess a common case would be a*B@x, where a is a scalar.  Is it more efficient or numerically stable to evaluate that one way or the other?<br><br>Aaron Meurer<br><br><br><blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir="ltr"><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> - Did you consider a duck-typing (is that the word?) attribute? <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   E.g. a*b is elementwise multiplication; a.M*b must be used for <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   matrix multiplication.  (Your use of .T as "transpose" made me think <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   of this.)  Of course the question is, can you get those packages <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   that currently use * for matrix multiply to comply? (I don't consider <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   this a serious counter-proposal. But you list a bunch of rejected <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   alternatives; this could be in that list. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>This is an interesting suggestion! I think it hasn't received full <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>consideration before because the tangle between numpy.ndarray and <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>numpy.matrix means that the most obvious implementation for an <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>ndarray.M attribute would be to return a full-fledged numpy.matrix <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>object... and no-one wants to encourage proliferation of numpy.matrix <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>objects. But returning a tiny special-purpose class that only <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>implements __mul__ would avoid that objection. At that point it's <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>basically a nicer version of the "user-defined infix" '*dot*' operator <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>idea. It has similar problems with needing an unaesthetically magical <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>implementation, producing a proliferation of special classes (one <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>extra one for each array type), requiring an allocation on every call, <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>etc., but this might well be the next-best thing to a real operator. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>All in all, I think we'd rather have a real operator, so if you're <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>happy to go with @ then I won't put lots of effort into finding <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>horrible problems that force us to reject .M ;-), but I'll certainly <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>add it to the PEP in any case. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> - Is @@ really necessary?  It seems you are adding it mostly because <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   it's cute and because of the parallel with **, not because it is <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   actually important enough to add new syntax.  And then later you use <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   it as an argument for @, which seems a bit circular.  Also, if we <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   were to make @ right-associative, the parallel with ** is already <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   imperfect. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>@@ hasn't received as much attention as the rest of the proposal, so <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>I'll check in with numpy-discussion etc. on this as well. But my <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>personal feeling is +0 on @@ -- all else being equal, it's nicer to <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>have it than not. Is all else equal? Given the existence of @, the <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>increase in language complexity is small (or arguably negative, since <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>people who know *, **, @ may be surprised to find @@ missing, and have <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>to memorize its non-existence as an extra rule); the opportunity cost <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>is low (given the existence of @ I can't imagine we'll want to use the <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>token @@ for something else later); and @@ will be used in real life, <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>if not as often as @ itself -- 'vec @@ 2' for squared Euclidean length <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>probably won't be too uncommon, 'matrix @@ n' gets used for things <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>like simulating random walks on graphs or other markov chains, and the <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>'matrix @@ -1' notation will probably be a nice win for beginners and <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>other less-sophisticated programmers who just want to get some <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>computation done in a way that doesn't require them to keep a more <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>complicated mapping between math and code notation in their head or <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>caring about numerical details. I think of @@ being like, say, '%=' -- <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>nothing one would ever add syntax for in isolation, but if designing <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>an overall system of operators then it makes more sense. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Probably in the end it just comes down to your aesthetic judgement <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>:-). Numeric folk will be fine either way. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>(And I wouldn't consider @@ a *strong* argument for spelling '@' as <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>'@'; it's just mentioned in that section because there aren't really <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>*any* strong arguments for preferring one spelling versus another, we <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>have to make a decision, and so a weak argument is better than <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>nothing. Two useful operators for the complexity cost of one is a good <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>deal? :shrug: Obviously if @@ gets dropped I'll drop that bullet point <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>as well.) <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> - For better counts of usages, perhaps Sourcegraph.com might help?  It <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   is a source code query engine that has a Python parser and (limited) <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   type inference built in (also separately available as pysonar on <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>>   github IIRC). To be clear, I don't need more numbers to be convinced. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Oo, that is shiny, thanks for the tip. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>> Once we've decided on associativity and @@, I'm ready to accept. <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Wonderful to hear! Thanks for giving this so much time and attention <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>(on no warning)! <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>-n <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote><br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>-- <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Nathaniel J. Smith <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Postdoctoral researcher - Informatics - University of Edinburgh <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote><a href="http://vorpus.org" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fvorpus.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHPr1_UuRsh28gntWJ7Q2PS3PaSWQ';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fvorpus.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHPr1_UuRsh28gntWJ7Q2PS3PaSWQ';return true;">http://vorpus.org</a> <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>______________________________<wbr>_________________ <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>Python-ideas mailing list <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote><a>Python...@python.org</a> <br><blockquote class="gmail_quote" style="margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote><a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank" onmousedown="this.href='https://www.google.com/url?q\75https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-ideas\46sa\75D\46sntz\0751\46usg\75AFQjCNFj1EaNHnVmh20FnFPoUi4J-MpfQw';return true;" onclick="this.href='https://www.google.com/url?q\75https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-ideas\46sa\75D\46sntz\0751\46usg\75AFQjCNFj1EaNHnVmh20FnFPoUi4J-MpfQw';return true;">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a> <br>Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fpython.org%2Fpsf%2Fcodeofconduct%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNHJOrArSUDKkjrnthO6_CznMzkPsA';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fpython.org%2Fpsf%2Fcodeofconduct%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNHJOrArSUDKkjrnthO6_CznMzkPsA';return true;">http://python.org/psf/<wbr>codeofconduct/</a>
<br></div></blockquote></div>