On Mon, Mar 17, 2014 at 12:50 PM, Alexander Belopolsky <ndarray@mac.com> wrote:

On Mon, Mar 17, 2014 at 12:13 PM, Nathaniel Smith <njs@pobox.com> wrote:
In practice all
well-behaved classes have to make sure that they implement __special__
methods in such a way that all the different variations work, no
matter which class ends up actually handling the operation.

"Well-behaved classes" are hard to come by in practice.  The @ operator may fix the situation with np.matrix, so take a look at MaskedArray with its 40-line __array_wrap__ and no end of bugs.

Requiring superclass __method__ to handle creation of subclass results correctly is turning Liskov principle on its head.  With enough clever tricks and tight control over the full class hierarchy you can make it work in some cases, but it is not a good design. 

I am afraid that making @ special among other binary operators that implement mathematically associative operations will create a lot of confusion.  (The pow operator is special because the corresponding mathematical operation is non-associative.)

Imagine teaching someone that a % b % c = (a % b) % c, but a @ b @ c = a @ (b @ c).  What are the chances that they will correctly figure out what a // b // c means after this? 

One case where we need to keep track of left or right is type promotion

>>> a.shape
(100,)
>>> 1. * a.dot(a)
-98.0
>>> (1.*a).dot(a)
328350.0
>>> a.dtype
dtype('int8')

>>> 1. * a @ a
???

similar to 
>>> 1. * 2 / 3
0.6666666666666666
>>> 1. * (2 / 3)   # I'm not in the `future`
0.0

Josef

 

_______________________________________________
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion

>>> 1. * a.dot(a)
-98.0