<div dir="ltr"><div dir="ltr">On Tue, Apr 23, 2019 at 12:27 AM Nathaniel Smith <<a href="mailto:njs@pobox.com">njs@pobox.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Mon, Apr 22, 2019 at 11:13 PM Stephan Hoyer <<a href="mailto:shoyer@gmail.com" target="_blank">shoyer@gmail.com</a>> wrote:<br>
><br>
>> On Mon, Apr 22, 2019 at 9:26 PM Nathaniel Smith <<a href="mailto:njs@pobox.com" target="_blank">njs@pobox.com</a>> wrote:<br>
>>><br>
>>> Your last email didn't really clarify anything for me. I get that np.func.__numpy_implementation__ is intended to have the semantics of numpy's implementation of func, but that doesn't tell me much :-). And also, that's exactly the definition of np.func, isn't it?<br>
><br>
> My understanding of the protocol we came up with in NEP-18 is that every NumPy function (that takes array-like arguments) now has two parts to its implementation:<br>
> 1. The NEP-18 part involving calling the dispatcher function, and checking for/calling __array_function__ attributes on array-like arguments. This part is documented in NEP-18.<br>
> 2. The original function definition, which is called if either (a) no __array_function__ attributes exist, or (b) the only __array_function__ attribute is numpy.ndarray.__array_function__. This part is documented in the docstring of the NumPy function.<br>
><br>
> "__numpy_implementation__" provides a short-cut to (2) without (1). That's it.<br>
<br>
OK, so the semantics are: the same as the normal function, except we<br>
pretend that none of the arguments have an __array_function__<br>
attribute?<br>
<br>
That's much clearer to me than how you were phrasing it before :-).<br></blockquote><div><br></div><div>OK, I will make sure something like this ends up in the NEP :)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Though now the name "__numpy_implementation__" doesn't seem very<br>
evocative of what it does... numpy's dispatch sequence has changed a<br>
lot in the past (mostly adding new coercion rules), and will probably<br>
change in the future, and "__numpy_implementation__" doesn't give much<br>
guidance about which parts of the dispatch sequence should be skipped<br>
as "dispatch" and which should be included as "implementation". Maybe<br>
something like __skipping_array_function__?</blockquote><div><br></div><div>With "__numpy_implementation__" I was hoping to evoke "the implementation used by numpy.ndarray.__array_function__" and "the implementation for NumPy arrays" rather than "the implementation found in the NumPy library." So it would still be appropriate to use on functions defined in SciPy, as long as they are defined on NumPy arrays.</div><div><br></div><div>That said, this is clearly going to remain a source of confusion. So let's see if we can do better.</div><div><br></div><div>Taking a step back, there will be three generic parts to NumPy functions after NEP-18:</div><div>1. Dispatching with __array_function__</div><div>2. Coercion to NumPy arrays (sometimes skipped if an object has the necessary duck-typing methods)</div><div>3. Implementation (either in C or is terms of other NumPy functions/methods)</div><div><br></div><div>Currently, NumPy functions do steps (2) and (3) together. What we're asking for here is a way to continue this behavior in the future, by optionally skipping step (1). But in the future, as Marten notes below, we should not rule out cases where we also want to skip straight to step (3), without step (2).</div><div><br></div><div><div>"__skipping_array_function__"  would be a reasonable choice, though it does not evoke the "numpy array specific"  aspect that I want to emphasis. Also, it has the unfortunate aspect of being named after what it doesn't do, rather than what it does.</div><div><br></div><div>"__numpy_ndarray_implementation__" and "__numpy_array_implementation__" are a bit verbose, but maybe they would be better?</div></div><div><br></div><div>The generic "__wrapped__" seems like a pretty bad choice to me, both because it's not at all descriptive and because it's generically used by functools.wraps -- which means np.ndarray.__array_function__ could inadvertently succeed when called with non-NumPy functions. Let's at least stick to unique names for our protocols :).</div></div></div>