<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Tue, Dec 12, 2017 at 6:20 PM 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">The real magic happens when you ducktype, and ensure your function<br>
works both for arrays and scalars on its own. This is more often<br>
possible than you might think!</blockquote><div><br></div><div>Sadly, this still doesn't work in a type-stable way.</div><div><br></div><div>NumPy's ufuncs convert 0-dimensional arrays into scalars. The typing rules for functions like np.sin() look like:</div><div>- scalar or 0d array -> scalar<br></div><div>- 1d or higher dimensional array -> array</div><div><br></div><div>I'm not entirely sure, but I suspect this was a practical rather than principled choice.</div><div><br></div><div>NumPy scalars are "duck arrays" of sorts (e.g., with shape and dtype attributes) which helps to some extent, but the bugs that slip through are even harder to understand. This wart reminds me of how mixed basic/advanced indexing reorders sliced dimensions to make the result more "intuitive", which only works in some cases.</div><div><br></div><div>I usually favor coercing all arguments to my functions to numpy arrays with np.asarray(), but to guarantee the return type you would also need to coerce it with np.asarray(), too.</div></div></div>