<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Mar 17, 2016 at 3:28 PM, Jaime Fernández del Río <span dir="ltr"><<a href="mailto:jaime.frio@gmail.com" target="_blank">jaime.frio@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><div>Would the logic for such a thing be consistent? E.g. how do you decide if the user is requesting (k),(k)->(), or (k),()->() with broadcasting over a non-core dimension of size k in the second argument? What if your signatures are (m, k),(k)->(m) and (k),(n,k)->(n) and your two inputs are (m,k) and (n,k), how do you decide which one to call? Or alternatively, how do you detect and forbid such ambiguous designs? Figuring out the dispatch rules for the general case seems like a non-trivial problem to me.</div></span></div></div></div></blockquote><div><br></div><div>I would require a priority order for the core signatures when the gufunc is created and only allow one implementation per argument dimension in the core signature (i.e., disallow multiple implementations like (k),(k)->() and (k),(m)->()).</div><div><br></div><div>The rule would be to dispatch to the implementation with the first core signature with the right number of axes. The later constraint ensures that (m,n) @ (k,n) errors if k != n, rather than attempting vectorized matrix-vector multiplication. For matmul/@, the priority order is pretty straightforward:</div><div>1. (m,n),(n,k)->(n,k)</div><div>2. (m,n),(n)->(m)</div><div>3. (m),(m,n)->(n)</div><div>4. (m),(m)->()</div><div><br></div><div>(2 and 3 could be safely interchanged.)</div><div><br></div><div>For scenarios like "(k),(k)->(), or (k),()->()", the only reasonable choice would be to put (k),(k)->() first -- otherwise it never gets called. For the other ambiguous case, "(m, k),(k)->(m) and (k),(n,k)->(n)", the implementer would also need to pick an order.</div><div><br></div><div>Most of the tricky cases for multiple dispatch arise from extensible systems (e.g., Matthew Rocklin's multipledispatch library), where you allow/encourage third party libraries to add their own implementations and need to be sure the combined result is still consistent. I wouldn't suggest such a system for NumPy -- I think it's fine to require every gufunc to have a single owner. There are other solutions for allowing extensibility to duck array types (namely, __numpy_ufunc__).</div><div><br></div></div></div></div>