<div dir="ltr"><div>My bad for such a convoluted example. All of this is trying to say something rather simple:</div><div><br></div><div>I'm sure almost all of you who've worked with C++ have used Boost header-only libraries. Many of them are really nice.</div><div><br></div><div>There are reasons why third-party Swift code might be distributed by one person and incorporated by another person in source form, a la Boost header-only libraries. One of these reasons would be that some compiler optimizations are not possible across module boundaries. With the implementation of your proposal, such third-party code could not be both incorporated as source (as opposed to a compiled module) and extended in certain ways without modifying the code itself. To me, that's a loss.</div><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 28, 2016 at 9:11 PM, Xiaodi Wu <span dir="ltr"><<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div class="h5"><div class="gmail_extra"><div class="gmail_quote">On Thu, Apr 28, 2016 at 8:32 PM, Erica Sadun <span dir="ltr"><<a href="mailto:erica@ericasadun.com" target="_blank">erica@ericasadun.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><br><div><blockquote type="cite"><div>On Apr 28, 2016, at 6:20 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><br><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Apr 28, 2016 at 6:44 PM, Erica Sadun <span dir="ltr"><<a href="mailto:erica@ericasadun.com" target="_blank">erica@ericasadun.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div>Can you give me a specific example of where this approach fails for you?</div><span><font color="#888888"><div><br></div><div>-- E</div></font></span></div></blockquote><div><br></div><div><br></div><div>Sure, I'll describe one (renaming some things for clarity and stripping out the meat of the code, because it's not relevant and because it's not elegant)--</div><div><br></div><div>In one file, I have:</div><div><br></div><div>```</div><div>class PortedTransfom {</div><div>// this class was ported from C++</div><div>// it transforms input FP values to output values in a complicated way</div><div>// it's a standalone entity and the algorithm is even under patent</div><div>// (not owned by me, though it's legal for me to use it for my purposes)</div><div>// for this reason, this ported code lives in its own file</div><div>}</div><div>```</div><div><br></div><div>In another file, I have:</div><div><br></div><div>```</div><div>class MyAsinhTransform {</div><div>// this class was written by me</div><div>// nothing earth-shattering here</div><div>}</div><div><br></div><div>class MyLogTransform {</div><div>// also written by me</div><div>}</div><div><br></div><div>class MyLinearTransform {</div><div>// also written by me</div><div>}</div><div>```</div><div><br></div><div>Transforming values one-at-a-time isn't fast enough, so in another file, I have:</div><div><br></div><div>```</div><div>import Accelerate</div><div><br></div><div>protocol AcceleratedTransform {</div><div> func scale(_: [Double]) -> [Double]</div><div> func unscale(_: [Double]) -> [Double]</div><div>// other functions here</div><div>// some are already implemented in PortedTransform, though</div><div>}</div><div>extension AcceleratedTransform {</div><div>// default implementations for some functions</div><div>// but not `scale(_:)` and `unscale(_:)`, obviously</div><div>}</div><div><br></div><div>extension MyAsinhTransform : AcceleratedTransform {</div><div>// use BLAS to implement scale(_:) and unscale(_:)</div><div>// and override some default implementations<br></div><div>}</div><div><br></div><div>extension MyLogTransform : AcceleratedTransform {</div><div>// use BLAS to implement scale(_:) and unscale(_:)</div><div>// and override some default implementations<br></div><div>}<br></div><div><br></div><div>extension MyLinearTransform : AcceleratedTransform {</div><div><div>// use BLAS to implement scale(_:) and unscale(_:)</div><div>// and override some default implementations<br></div><div>}<br></div></div><div><br></div><div>extension PortedTransform : AcceleratedTransform {</div><div>// use BLAS to implement scale(_:) and unscale(_:)</div><div>}</div><div>```</div></div></div></div></div></blockquote><br></div></div></div><div>I think I'm missing something here in terms of a question. Your imported stuff is your imported stuff.</div><div>Your extension implements "required" elements but not scale or unscale.</div><div><br></div><div>If you extend MyAsinhTransform, you do required but not override for scale/unscale. You do required override for anything you replace from AcceleratedTransform.</div><div>What is BLAS? And what are you specifically asking about?</div><div><br></div><div>-- E, apologizing for not understanding</div><br></div></blockquote></div><br></div></div></div><div class="gmail_extra">Sorry, stripped out a little too much, I guess. Let me expand a little:</div><div class="gmail_extra"><br></div><div class="gmail_extra">In this example, `PortedTransform` has, by virtue of how it works, an upper bound and lower bound for valid input (among other interesting methods and properties). Exceed those bounds for your input and `PortedTransform` regurgitates garbage but does not throw any kind of error. Obviously, linear transform does not care about such silly things because it can transform essentially any FP input value, while the log transform simply traps when it encounters a negative value (which, as a precondition, it should never encounter).</div><div class="gmail_extra"><br></div><div class="gmail_extra">BLAS is an accelerated linear algebra library; Apple has implemented a very nicely optimized one as part of its Accelerate framework. I use BLAS to sum, for example, two arrays of floating point values--it's very, very highly optimized. In that situation, there's no trapping when a single value is out of bounds (I get NaNs instead), and thus I must determine bounds in order to anticipate when the output will be garbage or NaN. (There are, as part of the Accelerate framework, accelerated functions to clamp entire arrays to given bounds with maximal efficiency).</div><div class="gmail_extra"><br></div><div class="gmail_extra">For accelerated scaling and unscaling, then, it is essentially always necessary to compute upper and lower bounds even when that's unnecessary for non-accelerated scaling and unscaling, which operates on one value at a time. For that reason, `AcceleratedTransform` requires methods that compute upper and lower bounds, and provides a default implementation of accelerated clamping that calls those bound-computing methods and then uses the results as parameters when calling functions in Accelerate.framework. Methods for the computation of bounds already exist in `PortedTransform` but not in my own transforms. With your proposal, how would I retroactively model this requirement without touching code for `PortedTransform` and without compiling this one class into its own library? I'd like to be able to take advantage of the maximum possible compiler optimization, and optimizing across module boundaries is (as far as I understand) a little dicier. (Moreover, for MyLinTransform, I override the clamping method to return the input without calling out to any framework functions because I know a priori that the bounds are -infinity and infinity. I think that override will still be possible under your proposal, though.)</div><div class="gmail_extra"><br></div></div>
</blockquote></div><br></div></div>