<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">This is a very real problem. It has come up a nontrivial number of times during my attempt to conform <a href="https://github.com/mattt/Surge" class="">Surge</a> to the API Guideline. My work in progress version is <a href="https://github.com/TheArtOfEngineering/Jolt" class="">here</a>.<div class=""><br class=""></div><div class="">Surge is in essence Swift a wrapper around the Accelerate framework. Originally the Surge API was constructed as a collection of global functions that mirrored the Accelerate framework exactly. I’m currently attempting to bring the API in line with the API Guideline and to extend CollectionType to have methods with these operations.</div><div class=""><br class=""></div><div class="">Thus I have three different types of API end points.</div><div class=""><br class=""></div><div class="">- Global functions</div><div class="">- Non-mutating methods</div><div class="">- Mutating methods</div><div class=""><br class=""></div><div class="">These distinctions could potentially be important given that these are all performance critical vector operations. Also given that this is extending the Accelerate framework many functions are named in mathematical terms, which makes them more difficult to name according to the current guidelines. Consider the following functions.</div><div class=""><br class=""></div><div class="">First let’s consider a function like `add` which operates on vectors and whose output is also a vector. This function is straightforward to conform to the API Guidelines, the result of which is quite satisfying. </div><div class=""><br class=""></div><div class="">The global function is called `add`, the mutating method is called `add`, and the non-mutating method is called `adding`.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>add(x, y) vs x.add(y) vs x.adding(y)</div><div class=""><br class=""></div><div class="">Excellent.</div><div class=""><br class=""></div><div class="">Next, however, consider the vector function `sum`. In this case the global function is named `sum`. There is no corresponding mutating method for `sum` since it does not output a vector. Should the non-mutating method therefore be called `sum` or `summed`? The Guideline is not so explicit about this. You could conceivably make an argument for either, although I think `sum` would win out because there is no non-mutating version. If there is no current mutating version for an API, but there could conceivably be one in the future, I assume that it should use the ‘ed/ing' rule. </div><div class=""><br class=""></div><div class="">sum(myVec) vs myVec.sum() // <- this is non-mutating</div><div class=""><div class=""><br class=""></div><div class="">So far, acceptable.</div><div class=""><br class=""></div><div class="">What about the function `sin`? </div><div class=""><br class=""></div><div class="">Again, the global function is just `sin`. How, though, do you distinguish the mutating and non-mutating methods?</div><div class=""><br class=""></div><div class="">sin(x) vs x.sin() vs x.sined()?</div><div class=""><br class=""></div><div class="">Fortunately, the API Guideline does have a comment on this. In the case of `sin`, it is reasonable to only provide the global function in accordance with mathematical convention. The problem is that memory constricted environments may require that the calculation be done in place. What that should look like is not clear.</div><div class=""><br class=""></div><div class="">What about functions that are almost always abbreviated by convention like `ceil`?</div><div class=""><br class=""></div><div class="">ceil(x) vs x.ceil() vs x.ceiled()</div><div class=""><br class=""></div><div class="">In this case the InPlace prefix can save us. x.ceilInPlace() would work.</div><div class=""><br class=""></div><div class="">Another good one is `remainder`.</div><div class=""><br class=""></div><div class="">remainder(x) vs x.remainder() vs x.remaindered() ?</div><div class=""><br class=""></div><div class="">These are just a few examples, but there are many many others in this API alone that the Guidelines struggle to address. Most are problematic for the same reasons outlined above. If it weren’t necessarily critical to reduce memory use it would suffice to just include the global function for many of them.</div><div class=""><br class=""></div><div class="">e.g.</div><div class="">reciprocal</div><div class="">threshold</div><div class="">floor</div><div class="">abs -> ???</div><div class="">exp -> x.exponentiated()?</div><div class="">exp2 or expSquared</div><div class="">logb</div><div class="">mean</div><div class="">dot</div><div class="">cross</div><div class=""><br class=""></div><div class="">For some functions like `dot` we could conceivably rely on the fact that familiar users would know that the return type is not the same as the arguments. I would argue however, that, if we were going to rely on the type information of the returned value then perhaps that’s what should be relied on exclusively to determine whether a method is mutating or not. </div><div class=""><br class=""></div><div class="">All mutating methods should return Void and all non mutating methods should have @warn_unused_result. Thus the context would distinguish it’s mutability. Not a huge fan of this, but with the unused warning result it’s not too bad.</div><div class=""><br class=""></div><div class="">For example.</div><div class=""><br class=""></div><div class="">let y = [...]</div><div class="">let x = y.remainder()</div><div class=""><br class=""></div><div class="">vs</div><div class=""><br class=""></div><div class="">var y = […]</div><div class="">y.remainder()</div><div class=""><br class=""></div><div class="">I hope this helps to give a little bit of color on a real world example outside of the standard library.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class=""><br class=""></div><div class="">Tyler</div><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 23, 2016, at 11:00 AM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class="">on Fri Jan 22 2016, Joe Groff <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">On Jan 22, 2016, at 1:57 PM, Jeff Kelley via swift-evolution<br class=""><<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""><blockquote type="cite" class="">On Jan 22, 2016, at 4:53 PM, Joe Groff via swift-evolution<br class=""><<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""></blockquote></blockquote><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><<a href="mailto:swift-evolution@swift.org" class="">mailto:swift-evolution@swift.org</a>>><br class="">wrote:<br class=""><br class="">How do you handle naming non-mutating versions of these operations?<br class="">Conjugating other irregular verbs also imposes a barrier on<br class="">developers whose first language is not English.<br class=""></blockquote><br class="">Swift could use “after” as a prefix, or something similar.<br class=""><br class="">array.sort()<br class="">array.afterSort()<br class=""><br class="">I was tempted to say “afterSorting()” but that has the same problems mentioned above.<br class=""></blockquote><br class="">That's reminiscent of the way the classic Cocoa naming guidelines<br class="">cleverly avoided these issues by using the 'did-' prefix consistently<br class="">instead of ever conjugating verbs into preterite tense. 'after' is a<br class="">bit awkward, though, as are any other equivalent prefixes i can think<br class="">of that have the same effect on the past participle (havingSplit?<br class="">bySplitting?)<br class=""></blockquote><br class="">"splitting" works perfectly well on its own, IMO. If there's an<br class="">argument to the method, you'll want some kind of preposition like "At"<br class="">or "On" afterwards.<br class=""><br class="">I think the real problem cases for this guideline as written are the<br class="">ones where there's no underlying verb, like "union", or where the verb<br class="">already has a strong non-mutating connotation, like "exclusiveOr."<br class="">Those are the ones that really cry out for a different convention, like<br class="">"InPlace." <br class=""><br class="">In developing the guidelines, we had some internal arguments about<br class="">whether it was worth adding complexity to accomodate those cases, or<br class="">whether we should simply not mention them and let them get sorted out on<br class="">a case-by-case basis when they come up in code review. We didn't reach<br class="">consensus, so this would be a useful area in which to get community<br class="">input.<br class=""><br class="">-- <br class="">-Dave<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></blockquote></div><br class=""></div></div></body></html>