Resolving the associativity/precedence debate for @
Hi all, After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this. The fundamental question is whether a chain like (a @ b @ c) should be evaluated left-to-right (left-associativity) or right-to-left (right-associativity). DATA SOURCE 1: This isn't a democratic vote, but it's useful to get a sense of people's intuitions. Counting messages in the other thread, opinion seems to be pretty evenly split: == "Votes" for right-associativity == Weak-right: [2] [3] [5] Tight-right: [4] [6] Same-right: [11] == "Votes" for left-associativity == Same-left: [7] [8] [14] [15] [16] Tight-left: [9] Weak-left: [12] There's also the "grouping" option (described in [10]), but that's received very little support (just [13]). DATA SOURCE 2: Several people have suggested that performance considerations mean that right-to-left evaluation is more common in practice than left-to-right evaluation. But, if we look at actual usage in Python code, that's not what we find: when people call dot() in chains, then they're about evenly split, and actually use the left-to-right, left-associative order slightly more often than the right-to-left, right-associative order: http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069578.html DATA SOURCE 3: And if we look at other languages, then we find: == "Votes" for right-associativity == <none> == "Votes" for left-associativity == Same-left: Matlab, Julia, IDL, GAUSS Tight-left: R And Mathematica uses the "grouping" approach. ARGUMENTS: The final outcome of this is that I need to write a piece of text that says what our (at least rough) consensus is, and lays out the reasons. So long as the "vote" is so evenly split, I can't really do this. But I can imagine what the different pieces of text might look like. THE CASE FOR LEFT-ASSOCIATIVITY: If I were writing this text in favor of left-associativity, I'd point out: - "Special cases aren't special enough to break the rules". Every single operator in Python besides ** is left-associative (and ** has very compelling arguments for right associativity). @ does not have similarly compelling arguments. If we were having this debate about "*", then it'd probably be much more lopsided towards left-associativity. So sure, there's something about @ that makes right-associativity *more* appealing than for most other operators. But not *much* more appealing -- left-associativity still comes out at least slightly ahead in all of the above measures. And there are a lot of benefits to avoiding special cases -- it gives fewer rules to memorize, fewer rules to remember, etc. So @ may be a special case, but it's not special enough. - Other languages with @ operators almost overwhelmingly use the "same-left" rule, and I've never heard anyone complain about this, so clearly nothing horrible will happen if we go this way. We have no comparable experience for right-associativity. - Given left-associativity, then there's good agreement about the appropriate precedence. If we choose right-associativity then it's much less clear (which will then make things harder for experts to remember, harder for non-experts to guess, etc.). Note that one of the votes for right-associativity even preferred the "same-right" rule, which is not even technically possible... This strikes me as a nice solid case. THE CASE FOR RIGHT-ASSOCIATIVITY: If I were writing this text in favor of right-associativity, I'd point out: - Because matrix multiplication has a tight conceptual association with function application/composition, many mathematically sophisticated users have an intuition that a matrix expression like R S x proceeds from right-to-left, with first S transforming x, and then R transforming the result. This isn't universally agreed, but at the least this intuition is more common than for other operations like 2 * 3 * 4 that everyone reads as going from left-to-right. - There might be some speed argument, if people often write things like "Mat @ Mat @ vec"? But no-one has found any evidence that people actually do write such things often. - There's been discussion of how right-associativity might maybe perhaps be nice for non-matmul applications? But I can't use those arguments [17] [18]. - ...... I got nothin'. I am fine with any outcome here. (I'm actually listed under *both* tight-right and same-left in the straw poll above ;-).) I'm totally happy to go back to Guido et al and argue for right-associativity. BUT if you all want me to do that then you need to give me some better arguments to use :-). One way to do this might be to go through the ((a @ b) @ c) and (a @ (b @ c)) examples I found (the scripts are available [19], and I can help modify them to spit out more details), look at the actual code, and demonstrate that the left-to-right ((a @ b) @ c) cases are mostly ones where evaluation order doesn't matter (i.e., they could have just as well been written the other way), and the right-to-left (a @ (b @ c)) ones are ones where right-to-left really is better than left-to-right. I have no idea if this is true, and it'll require some reading of the surrounding code to figure out what the matrix shapes are, but if it *is* true then at least that'd be something solid that right-associativity advocates could point to. WHAT NOW: If seeing this summary laid out caused you to change your mind one way or the other, then please reply and say so! If you think of some way to get more data that could favor one or the other option (running some kind of usability experiment on people? [20]), then please share! If you think of some other arguments in favor of left-associativity, then please share! If you think of some other arguments in favor of right-associativity, especially ones that are based on something besides your gut feeling, then PLEASE PLEASE share! Thanks, -n [1] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069444.html [2] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069446.html [3] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069450.html [4] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069452.html [5] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069455.html [6] https://mail.python.org/pipermail/python-ideas/2014-March/027124.html [7] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069512.html [8] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069513.html [9] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069467.html [10] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069530.html [11] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069537.html [12] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069540.html [13] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069571.html [14] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069514.html [15] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069531.html [16] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069567.html [17] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069527.html [18] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069584.html [19] https://gist.github.com/njsmith/9157645 [20] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069584.html -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org
Hi Nate, Many thanks first for the efforts you put in this. I'm not a computer scientist, but will give my opinion as physicist. As such, when I see A x B x C (A, B and C being matrices), I tend to read it from right to left : Ax (BxC). But if the size of the matrices do not match like this, then I'll read it the other way round. Moreover, matrix diagonalization is always written so that the operations are done from right to left (P^-1 x A x P is read do AxP first, then multiply by P⁻1) Éric. -- Un clavier azerty en vaut deux ---------------------------------------------------------- Éric Depagne eric@depagne.org
On Sat, Mar 22, 2014 at 2:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
If you think of some other arguments in favor of left-associativity, then please share!
I argued on python-ideas [1] that given the display properties of python lists and numpy arrays, vec @ Mat is more natural than Mat @ vec. The latter comes from an old tradition of laying out vector components vertically in print and on a blackboard, but horizontal layout is more natural at python prompt and in a text editor. [1] https://mail.python.org/pipermail/python-ideas/2014-March/027169.html
On 2014/03/22 8:13 AM, Nathaniel Smith wrote:
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist:-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
In case a "vote" from a previously "non-voting" reader helps: I think the case for same-left, as you state it, is strong; it's simple and easy to remember, and *this* *matters*. A *strong* argument would be needed to override this consideration, and I haven't seen any such strong argument. The basic advice to users is: be explicit--use parentheses as needed to show both the interpreter and readers of your code how you want the expression to be evaluated. Relying on precedence and associativity works only when the rules are well established by convention, and the expression is quite simple. Eric
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
"The numpy community has no consensus strongly preferring one option over another" is a perfectly fine conclusion to this thread on numpy-discussion, IMO. Actually deciding what goes into the PEP given that input and merged with other concerns should probably happen on python-ideas. -- Robert Kern
On Sat, Mar 22, 2014 at 7:59 PM, Robert Kern <robert.kern@gmail.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
"The numpy community has no consensus strongly preferring one option over another" is a perfectly fine conclusion to this thread on numpy-discussion, IMO. Actually deciding what goes into the PEP given that input and merged with other concerns should probably happen on python-ideas.
Yep, if we converge on deadlock then that's what we'll do, but I'm not yet convinced that we've converged at all. In the last few hours the "vote" deltas are right -1, left +3... -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org
On Sun, Mar 23, 2014 at 3:14 AM, Nathaniel Smith <njs@pobox.com> wrote:
On Sat, Mar 22, 2014 at 7:59 PM, Robert Kern <robert.kern@gmail.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
"The numpy community has no consensus strongly preferring one option over another" is a perfectly fine conclusion to this thread on numpy-discussion, IMO. Actually deciding what goes into the PEP given that input and merged with other concerns should probably happen on python-ideas.
Yep, if we converge on deadlock then that's what we'll do, but I'm not yet convinced that we've converged at all. In the last few hours the "vote" deltas are right -1, left +3...
If it helps, my +1 is also for left associative. Ralf
Hi, On 22 March 2014 19:13, Nathaniel Smith wrote:
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
The fundamental question is whether a chain like (a @ b @ c) should be evaluated left-to-right (left-associativity) or right-to-left (right-associativity).
<snip> I have been following this discussion and the PEP with much interest and, just to state the obvious, the addition of a matrix-multiplication operator in Python is way overdue. If I had to judge from the oil industry point of view only, in recent years the adoption of Python (and, by consequence, NumPy) as a number crunching platform has grown exponentially. I could cite dozens of non-performance-critical examples of commercial tools that switched from close-to-unmantainable Fortran/C implementations or (please forgive us...) hieroglyphic-style Perl code to Python. That said, if you're still interested in a social experiment about the precedence of "@", I can share a real-life one - albeit on a small sample of people (15). This is the background: 1. I'm about to teach an internal course on Python/NumPy/other in the company, so I polled the participants on their intuition about the "@" operator precedence; 2. We are *not* math gurus, but we do use NumPy on terabyte-scale data pretty much on a daily basis; 3. We are not "heavy" users of the "dot' method, but our various pieces of code contains quite a few calls to it; 4. All Python operators have left-associativity, excluding "**"; 5. Python code is read left-to-right. So, by asking the question: how do you interpret the expression "a @ b @ c", this is a summary of what I got from the participants: 1. Twelve (12) said they would interpret it as: "first do a@b, then matrix-multiply the results with c"; 2. Two (2) said they had no idea; 3. One (1) applied the right-associativity rule; 4. Whatever the Numpy-dev or Python-dev decision is, no one of us is ever, *ever* going to write "a @ b @ c" without parenthesis, to make clear the ordering of operations. I'm not going to pass judgments on the social experiment nor to invoke the Zen here, even though I fail to see how "@" is such a special case to break the standard rules. Not every NumPy user is a high-level math-educated person, or even if he/she is, he/she may have forgotten the basics of it. Why confuse him/her more? Andrea. "Imagination Is The Only Weapon In The War Against Reality." http://www.infinity77.net # ------------------------------------------------------------- # def ask_mailing_list_support(email): if mention_platform_and_version() and include_sample_app(): send_message(email) else: install_malware() erase_hard_drives() # ------------------------------------------------------------- #
On Sat, Mar 22, 2014 at 12:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
The fundamental question is whether a chain like (a @ b @ c) should be evaluated left-to-right (left-associativity) or right-to-left (right-associativity).
DATA SOURCE 1:
This isn't a democratic vote, but it's useful to get a sense of people's intuitions. Counting messages in the other thread, opinion seems to be pretty evenly split:
== "Votes" for right-associativity == Weak-right: [2] [3] [5] Tight-right: [4] [6] Same-right: [11]
== "Votes" for left-associativity == Same-left: [7] [8] [14] [15] [16] Tight-left: [9] Weak-left: [12]
There's also the "grouping" option (described in [10]), but that's received very little support (just [13]).
DATA SOURCE 2:
Several people have suggested that performance considerations mean that right-to-left evaluation is more common in practice than left-to-right evaluation. But, if we look at actual usage in Python code, that's not what we find: when people call dot() in chains, then they're about evenly split, and actually use the left-to-right, left-associative order slightly more often than the right-to-left, right-associative order: http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069578.html
DATA SOURCE 3:
And if we look at other languages, then we find:
== "Votes" for right-associativity == <none>
== "Votes" for left-associativity == Same-left: Matlab, Julia, IDL, GAUSS Tight-left: R
And Mathematica uses the "grouping" approach.
ARGUMENTS:
The final outcome of this is that I need to write a piece of text that says what our (at least rough) consensus is, and lays out the reasons. So long as the "vote" is so evenly split, I can't really do this. But I can imagine what the different pieces of text might look like.
THE CASE FOR LEFT-ASSOCIATIVITY:
If I were writing this text in favor of left-associativity, I'd point out:
- "Special cases aren't special enough to break the rules". Every single operator in Python besides ** is left-associative (and ** has very compelling arguments for right associativity). @ does not have similarly compelling arguments. If we were having this debate about "*", then it'd probably be much more lopsided towards left-associativity. So sure, there's something about @ that makes right-associativity *more* appealing than for most other operators. But not *much* more appealing -- left-associativity still comes out at least slightly ahead in all of the above measures. And there are a lot of benefits to avoiding special cases -- it gives fewer rules to memorize, fewer rules to remember, etc. So @ may be a special case, but it's not special enough.
- Other languages with @ operators almost overwhelmingly use the "same-left" rule, and I've never heard anyone complain about this, so clearly nothing horrible will happen if we go this way. We have no comparable experience for right-associativity.
- Given left-associativity, then there's good agreement about the appropriate precedence. If we choose right-associativity then it's much less clear (which will then make things harder for experts to remember, harder for non-experts to guess, etc.). Note that one of the votes for right-associativity even preferred the "same-right" rule, which is not even technically possible...
This strikes me as a nice solid case.
THE CASE FOR RIGHT-ASSOCIATIVITY:
If I were writing this text in favor of right-associativity, I'd point out:
- Because matrix multiplication has a tight conceptual association with function application/composition, many mathematically sophisticated users have an intuition that a matrix expression like R S x proceeds from right-to-left, with first S transforming x, and then R transforming the result. This isn't universally agreed, but at the least this intuition is more common than for other operations like 2 * 3 * 4 that everyone reads as going from left-to-right.
- There might be some speed argument, if people often write things like "Mat @ Mat @ vec"? But no-one has found any evidence that people actually do write such things often.
- There's been discussion of how right-associativity might maybe perhaps be nice for non-matmul applications? But I can't use those arguments [17] [18].
- ...... I got nothin'.
I am fine with any outcome here. (I'm actually listed under *both* tight-right and same-left in the straw poll above ;-).) I'm totally happy to go back to Guido et al and argue for right-associativity. BUT if you all want me to do that then you need to give me some better arguments to use :-).
One way to do this might be to go through the ((a @ b) @ c) and (a @ (b @ c)) examples I found (the scripts are available [19], and I can help modify them to spit out more details), look at the actual code, and demonstrate that the left-to-right ((a @ b) @ c) cases are mostly ones where evaluation order doesn't matter (i.e., they could have just as well been written the other way), and the right-to-left (a @ (b @ c)) ones are ones where right-to-left really is better than left-to-right. I have no idea if this is true, and it'll require some reading of the surrounding code to figure out what the matrix shapes are, but if it *is* true then at least that'd be something solid that right-associativity advocates could point to.
WHAT NOW:
If seeing this summary laid out caused you to change your mind one way or the other, then please reply and say so!
If you think of some way to get more data that could favor one or the other option (running some kind of usability experiment on people? [20]), then please share!
If you think of some other arguments in favor of left-associativity, then please share!
If you think of some other arguments in favor of right-associativity, especially ones that are based on something besides your gut feeling, then PLEASE PLEASE share!
Well, I this point I think we might as well go with left associativity. Most of the operator uses looked to involve a single `@`, where it doesn't matter, and the others were short where adding a couple of parenthesis wouldn't mess things up too much. The long expressions I've seen also tend to group naturally and probably one would either compute the parts separately or use parenthesis for clarity in any case. So I think the case for the practical usefulness of right associativity is weak at this point. <snip> Chuck
Charles R Harris <charlesr.harris@gmail.com> wrote:
Well, I this point I think we might as well go with left associativity. Most of the operator uses looked to involve a single `@`, where it doesn't matter, and the others were short where adding a couple of parenthesis wouldn't mess things up too much.
That is what most Python operators do. Right associativity will just be confusing. ** is right associative because of the way exponentiation is written in text. As I see it, left associativity of @ is clearly the better option. Sturla
Nathaniel Smith <njs@pobox.com> wrote:
- There might be some speed argument, if people often write things like "Mat @ Mat @ vec"? But no-one has found any evidence that people actually do write such things often.
With left associativity, this would be an algorithmic optimization: Mat @ (Mat @ vec) Mat @ (Mat @ (Mat @ vec)) On the other hand, this vec.T @ Mat @ Mat would not need parentheses for optimisation when the associativity is left. With right associativity, we get the same optimisation problem as well: (vec.T @ Mat) @ Mat ((vec.T @ Mat) @ Mat) @ Mat Personally I believe this advice to the novice programmer belongs in the documentation. If we just include it in the NumPy documentation, it will not be a problem. Advices about how to optimize numerical expressions should not be special cases in the syntax, in my opinion. That just makes the Python language harder to learn. Rather, it is a documentation problem for NumPy. We should write the NumPy documentation for @ such that the novice programmer easily understands the computational complexities of linear algebra operations. The PEP might include this as well, so the knowledge propagates into the rest of the Python language litterature, not just the NumPy docs. By the way, the * operator for np.matrix and Matlab matrices are left associative as well. This does not produce any problems. Sturla
On Sat, Mar 22, 2014 at 10:35 PM, Sturla Molden <sturla.molden@gmail.com
wrote:
On the other hand, this
vec.T @ Mat @ Mat
would not need parentheses for optimisation when the associativity is left.
Nor does it require .T if vec is 1d.
By the way, the * operator for np.matrix and Matlab matrices are left associative as well.
This is a very strong argument, IMO. If we want to win over the hearts of np.matrix users, we should not tell them - BTW - treat @ as you do **, not *.
Hi, Le 22/03/2014 19:13, Nathaniel Smith a écrit :
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this. Thanks for this nice summary. I found the previous thread very interesting to follow.
My first reaction when the associativity question was raised was : why would anyone want this non-standard right-associativity ? Indeed, I don't see the special case of Mat*Mat*vec to be important enough to break the common convention. Then, I almost got convinced by the function composition argument. It looks quite elegant, but in the end, there is no current mainstream usage. Also, somebody could use the new @ operator to perform function composition (and not function application) like this : (f@g@h)(x) I don't know where it could be used, but there could be some fun. Then, there is the multiplication chaining, but that belongs clearly to some other discussion, because that's getting close to lazy evaluation with underlying operation optimization. Indeed, why stop at just optimizating just the multiplication ?For this kind of expression-level optim, there is clearly no standard solution : numexpr, theano, ... ? (not familiar with this topic) So +1 for a plain and simple left associativity. (for weak or same, I don't think I understood all the aspects, but I feel that "same" is also the simplest choice) best, Pierre
Le 22/03/2014 19:13, Nathaniel Smith a écrit :
Hi all,
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
The fundamental question is whether a chain like (a @ b @ c) should be evaluated left-to-right (left-associativity) or right-to-left (right-associativity).
DATA SOURCE 1:
This isn't a democratic vote, but it's useful to get a sense of people's intuitions. Counting messages in the other thread, opinion seems to be pretty evenly split:
== "Votes" for right-associativity == Weak-right: [2] [3] [5] Tight-right: [4] [6] Same-right: [11]
== "Votes" for left-associativity == Same-left: [7] [8] [14] [15] [16] Tight-left: [9] Weak-left: [12]
There's also the "grouping" option (described in [10]), but that's received very little support (just [13]).
DATA SOURCE 2:
Several people have suggested that performance considerations mean that right-to-left evaluation is more common in practice than left-to-right evaluation. But, if we look at actual usage in Python code, that's not what we find: when people call dot() in chains, then they're about evenly split, and actually use the left-to-right, left-associative order slightly more often than the right-to-left, right-associative order: http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069578.html
DATA SOURCE 3:
And if we look at other languages, then we find:
== "Votes" for right-associativity == <none>
== "Votes" for left-associativity == Same-left: Matlab, Julia, IDL, GAUSS Tight-left: R
This is a very strong point. Lots of people come to python with a background and would be surprised if python behaves differently than other mainstream frameworks. I'll add that simpler is better, multiplications should behave the same way, and vote for same-left.
And Mathematica uses the "grouping" approach.
ARGUMENTS:
The final outcome of this is that I need to write a piece of text that says what our (at least rough) consensus is, and lays out the reasons. So long as the "vote" is so evenly split, I can't really do this. But I can imagine what the different pieces of text might look like.
THE CASE FOR LEFT-ASSOCIATIVITY:
If I were writing this text in favor of left-associativity, I'd point out:
- "Special cases aren't special enough to break the rules". Every single operator in Python besides ** is left-associative (and ** has very compelling arguments for right associativity). @ does not have similarly compelling arguments. If we were having this debate about "*", then it'd probably be much more lopsided towards left-associativity. So sure, there's something about @ that makes right-associativity *more* appealing than for most other operators. But not *much* more appealing -- left-associativity still comes out at least slightly ahead in all of the above measures. And there are a lot of benefits to avoiding special cases -- it gives fewer rules to memorize, fewer rules to remember, etc. So @ may be a special case, but it's not special enough.
- Other languages with @ operators almost overwhelmingly use the "same-left" rule, and I've never heard anyone complain about this, so clearly nothing horrible will happen if we go this way. We have no comparable experience for right-associativity.
- Given left-associativity, then there's good agreement about the appropriate precedence. If we choose right-associativity then it's much less clear (which will then make things harder for experts to remember, harder for non-experts to guess, etc.). Note that one of the votes for right-associativity even preferred the "same-right" rule, which is not even technically possible...
This strikes me as a nice solid case.
THE CASE FOR RIGHT-ASSOCIATIVITY:
If I were writing this text in favor of right-associativity, I'd point out:
- Because matrix multiplication has a tight conceptual association with function application/composition, many mathematically sophisticated users have an intuition that a matrix expression like R S x proceeds from right-to-left, with first S transforming x, and then R transforming the result. This isn't universally agreed, but at the least this intuition is more common than for other operations like 2 * 3 * 4 that everyone reads as going from left-to-right.
- There might be some speed argument, if people often write things like "Mat @ Mat @ vec"? But no-one has found any evidence that people actually do write such things often.
- There's been discussion of how right-associativity might maybe perhaps be nice for non-matmul applications? But I can't use those arguments [17] [18].
- ...... I got nothin'.
I am fine with any outcome here. (I'm actually listed under *both* tight-right and same-left in the straw poll above ;-).) I'm totally happy to go back to Guido et al and argue for right-associativity. BUT if you all want me to do that then you need to give me some better arguments to use :-).
One way to do this might be to go through the ((a @ b) @ c) and (a @ (b @ c)) examples I found (the scripts are available [19], and I can help modify them to spit out more details), look at the actual code, and demonstrate that the left-to-right ((a @ b) @ c) cases are mostly ones where evaluation order doesn't matter (i.e., they could have just as well been written the other way), and the right-to-left (a @ (b @ c)) ones are ones where right-to-left really is better than left-to-right. I have no idea if this is true, and it'll require some reading of the surrounding code to figure out what the matrix shapes are, but if it *is* true then at least that'd be something solid that right-associativity advocates could point to.
WHAT NOW:
If seeing this summary laid out caused you to change your mind one way or the other, then please reply and say so!
If you think of some way to get more data that could favor one or the other option (running some kind of usability experiment on people? [20]), then please share!
If you think of some other arguments in favor of left-associativity, then please share!
If you think of some other arguments in favor of right-associativity, especially ones that are based on something besides your gut feeling, then PLEASE PLEASE share!
Thanks, -n
[1] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069444.html [2] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069446.html [3] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069450.html [4] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069452.html [5] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069455.html [6] https://mail.python.org/pipermail/python-ideas/2014-March/027124.html [7] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069512.html [8] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069513.html [9] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069467.html [10] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069530.html [11] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069537.html [12] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069540.html [13] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069571.html [14] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069514.html [15] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069531.html [16] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069567.html [17] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069527.html [18] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069584.html [19] https://gist.github.com/njsmith/9157645 [20] http://mail.scipy.org/pipermail/numpy-discussion/2014-March/069584.html
--- Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active. http://www.avast.com
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
Response in this thread so far seems (AFAICT) to have pretty much converged on same-left. If you think that this would be terrible and there is some compelling argument against it, then please speak up! Otherwise, if no-one objects, then I'll go ahead in the next few days and put same-left into the PEP. -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org
On Mon, Mar 24, 2014 at 5:56 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
Response in this thread so far seems (AFAICT) to have pretty much converged on same-left.
If you think that this would be terrible and there is some compelling argument against it, then please speak up! Otherwise, if no-one objects, then I'll go ahead in the next few days and put same-left into the PEP.
I think we should take a close look at broadcasting before deciding on the precedence. Chuck
On Mon, Mar 24, 2014 at 11:58 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Mon, Mar 24, 2014 at 5:56 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
Response in this thread so far seems (AFAICT) to have pretty much converged on same-left.
If you think that this would be terrible and there is some compelling argument against it, then please speak up! Otherwise, if no-one objects, then I'll go ahead in the next few days and put same-left into the PEP.
I think we should take a close look at broadcasting before deciding on the precedence.
Can you elaborate? Like what, concretely, do you think we need to do now? -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org
On Mon, Mar 24, 2014 at 8:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Mon, Mar 24, 2014 at 11:58 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Mon, Mar 24, 2014 at 5:56 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
Response in this thread so far seems (AFAICT) to have pretty much converged on same-left.
If you think that this would be terrible and there is some compelling argument against it, then please speak up! Otherwise, if no-one objects, then I'll go ahead in the next few days and put same-left into the PEP.
I think we should take a close look at broadcasting before deciding on the precedence.
Can you elaborate? Like what, concretely, do you think we need to do now?
??? "In examples like this, parenthesizing the code aggressively to spell out the logic, not only to Stata but also to yourself and anybody else reading it, should cause no embarrassment. You need not assume knowledge of Stata's precedence rules that determine interpretation when several operators are used in one expression. More importantly, you may avoid some horrible little bugs." Nicholas J. Cox Trying to figure out what Stata is using: elementwise operations are just below their matrix version in operator precedence. But Stata came late to matrix algebra, and is definitely not like Matlab or Gauss, or numpy. Josef
-n
-- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
On Mon, Mar 24, 2014 at 6:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Mon, Mar 24, 2014 at 5:56 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
Response in this thread so far seems (AFAICT) to have pretty much converged on same-left.
If you think that this would be terrible and there is some compelling argument against it, then please speak up! Otherwise, if no-one objects, then I'll go ahead in the next few days and put same-left into the PEP.
I think we should take a close look at broadcasting before deciding on
On Mon, Mar 24, 2014 at 11:58 PM, Charles R Harris <charlesr.harris@gmail.com> wrote: the
precedence.
Can you elaborate? Like what, concretely, do you think we need to do now?
Mostly I like to think of the '@' operators like commas in a function call where each argument gets evaluated before the matrix multiplications take place, so that would put it of lower precedence than '*', but still higher than '+, -' . However, since most matrix expressions seem to be small it may not matter much and the same result could be gotten with parenthesis. But I do think it would make it easier to read and parse matrix expressions as the '@' would serve as a natural divider. So 'A @ B*v' would be equivalent to 'A @ (B*v)' and not '(A @B)*v'. Hmm, now that I stare at it, it may actually be easier to simply read left to right and use parenthesis when needed. So put me down as neutral at this point and maybe trending towards equal precedence. Chuck
On Tue, Apr 1, 2014 at 4:13 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Mon, Mar 24, 2014 at 6:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Mon, Mar 24, 2014 at 11:58 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Mon, Mar 24, 2014 at 5:56 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Sat, Mar 22, 2014 at 6:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
After 88 emails we don't have a conclusion in the other thread (see [1] for background). But we have to come to some conclusion or another if we want @ to exist :-). So I'll summarize where the discussion stands and let's see if we can find some way to resolve this.
Response in this thread so far seems (AFAICT) to have pretty much converged on same-left.
If you think that this would be terrible and there is some compelling argument against it, then please speak up! Otherwise, if no-one objects, then I'll go ahead in the next few days and put same-left into the PEP.
I think we should take a close look at broadcasting before deciding on the precedence.
Can you elaborate? Like what, concretely, do you think we need to do now?
Mostly I like to think of the '@' operators like commas in a function call where each argument gets evaluated before the matrix multiplications take place, so that would put it of lower precedence than '*', but still higher than '+, -' . However, since most matrix expressions seem to be small it may not matter much and the same result could be gotten with parenthesis. But I do think it would make it easier to read and parse matrix expressions as the '@' would serve as a natural divider. So 'A @ B*v' would be equivalent to 'A @ (B*v)' and not '(A @B)*v'.
Hmm, now that I stare at it, it may actually be easier to simply read left to right and use parenthesis when needed. So put me down as neutral at this point and maybe trending towards equal precedence.
Okay, I'm going to let that be the last word on this (unless someone wants a laster word, but no-one seems too eager at this point). We have to pick something, we seem to have mostly converged on left-associativity, and the bulk of the opinion on left-associativity is clearly for same-left, so I've updated the PEP to include @ parsing as same-left: https://github.com/njsmith/numpy/blob/matmul-pep/doc/neps/return-of-revenge-... Thanks everyone for your feedback, both here and throughout the process in general -- I know this has been a long discussion to slog through! -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org
participants (12)
-
Alexander Belopolsky
-
Andrea Gavana
-
Charles R Harris
-
Eric Firing
-
josef.pktd@gmail.com
-
Joseph Martinot-Lagarde
-
Nathaniel Smith
-
Pierre Haessig
-
Ralf Gommers
-
Robert Kern
-
Sturla Molden
-
Éric Depagne