[Numpy-discussion] [help needed] associativity and precedence of '@'

Nathaniel Smith njs at pobox.com
Wed Mar 19 14:24:18 EDT 2014


On Tue, Mar 18, 2014 at 9:14 AM, Robert Kern <robert.kern at gmail.com> wrote:
> On Tue, Mar 18, 2014 at 12:54 AM, Nathaniel Smith <njs at pobox.com> wrote:
>> On Sat, Mar 15, 2014 at 6:28 PM, Nathaniel Smith <njs at pobox.com> wrote:
>>> Mathematica: instead of having an associativity, a @ b @ c gets
>>> converted into mdot([a, b, c])
>>
>> So, I've been thinking about this (thanks to @rfateman for pointing it
>> out), and wondering if Mathematica's approach is worth following up
>> more. (It would need to make it past python-dev, of course, but worst
>> case is just that they say no and we're back where we are now, so we
>> might as well think it through.)
>
> I predict with near-certainty that this will be rejected,

I guess that's what everyone thought about @ too? ;-)

> but that
> doesn't prevent it from derailing the discussion. This proposal is
> unlike anything else in Python. Chained comparisons are *not* similar
> to this proposal. The chaining only happens at the syntax level, not
> the semantics. `a < b < c` gets compiled down to `a.__lt__(b) and
> b.__lt__(c)`, not `do_comparison([a, b, c], [lt, lt])`.

Yes, the syntax is the same as chained comparisons, and the dispatch
is a generalization of regular operators. It is unusual; OTOH, @ is
unusual in that no other operators in Python have the property that
evaluating in the wrong order can cost you seconds of time and
gigabytes of memory. Perhaps.

> We have approval for a binary @ operator. Take the win.

We have approval, and we have a request: that we figure out how @
should work in detail to be most useful to us. Maybe that's this
proposal; maybe not. Ultimately rejected-or-not-rejected comes down to
how strong the arguments for something are. And while we can make some
guesses about that, it's impossible to know how strong an argument
will be until one sits down and works it out. So I still would like to
hear what people think, even if it just ends in the conclusion that
it's a terrible idea ;-).

As for arguments against the "grouping" semantics, I did think of one
another case where @ is not associative, though it's pretty weird:

In [9]: a = np.arange(16, dtype=np.int8).reshape((4, 4))

In [10]: np.dot(a, np.dot(a, a.astype(float)))
Out[10]:
array([[  1680.,   1940.,   2200.,   2460.],
       [  4880.,   5620.,   6360.,   7100.],
       [  8080.,   9300.,  10520.,  11740.],
       [ 11280.,  12980.,  14680.,  16380.]])

In [12]: np.dot(np.dot(a, a), a.astype(float))
Out[12]:
array([[ 1680.,  1940.,  2200.,  2460.],
       [-1264., -1548., -1832., -2116.],
       [ 1936.,  2132.,  2328.,  2524.],
       [-1008., -1100., -1192., -1284.]])

(What's happening is that we have int8 @ int8 @ float, so (int8 @
int8) @ float has overflows in the first computation, but int8 @ (int8
@ float) does all the computations in float, with no overflows.)

-- 
Nathaniel J. Smith
Postdoctoral researcher - Informatics - University of Edinburgh
http://vorpus.org



More information about the NumPy-Discussion mailing list