<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Sun, Jun 3, 2018 at 11:12 AM Marten van Kerkwijk <<a href="mailto:m.h.vankerkwijk@gmail.com">m.h.vankerkwijk@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Jun 3, 2018 at 2:00 PM, Hameer Abbasi <span dir="ltr"><<a href="mailto:einstein.edison@gmail.com" target="_blank">einstein.edison@gmail.com</a>></span> wrote:<br></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><ul style="font-stretch:normal;line-height:17px;background-color:rgba(0,0,0,0)"><li>Objects that don’t implement ``__array_function__`` should be treated as having returned ``np.NotImplementedButCoercible``.</li><ul><li>This has the effect of coercing ``list``, etc.</li><li>At a minimum, to maintain compatibility, if all objects don’t implement ``__array_function__``, the old behaviour should stay.</li></ul></ul></div></div></blockquote></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>I think that in the proposed scheme this is effectively what happens.</div></div></div></div></blockquote><div><br></div><div>The current proposal is to copy the behavior of __array_ufunc__. So the non-existence of an __array_function__ attribute is indeed *not* equivalent to returning NotImplemented: if no arguments implement __array_function__, then yes they will all be coerced to NumPy arrays.</div><div><br></div><div>I do think there is elegance in defining a return value of np.NotImplementedButCoercible as equivalent to the existence of __array_function__. This resolves my design question about how coercible arguments would be coerced with NotImplementedButCoercible: we would fall back to the current behavior, which in most cases means all arguments are coerced to NumPy arrays directly. Mixed return values of NotImplementedButCoercible and NotImplemented would still result in TypeError, and there would be no second chances for overloads.</div><div><br></div><div>This is simple enough that I am inclined to update the NEP to incorporate the suggestion (thank you!).</div><div><br></div><div>My main question is whether we should also update __array_ufunc__ to support returning NotImplementedButCoercible for consistency. My inclination is yes: even though it's easy to implement a fallback of converting all arguments to NumPy arrays for ufuncs, it is hard to do this correctly from an __array_ufunc__ implementation, because __array_ufunc__ implementations do not know in what order they have been called.</div><div><br></div><div>The counter-argument would be that it's not worth adding new features to __array_ufunc__ if use-cases haven't come up yet. But my guess is that most users/implementors of __array_ufunc__ are ignorant of these finer details, and not really worrying about them. Also, the list of binary operators in Python is short enough that most implementations are OK with supporting either all or none.</div><div><br></div><div>Actually, a return value of NotImplementedButCoercible would probably be the right answer for some cases in xarray's current __array_ufunc__ method, when we encounter ufunc methods for which we haven't written an implementation (e.g., "outer" or "at").</div></div></div>