[swift-evolution] [Review] SE-0023 API Design Guidelines
Jacob Bandes-Storch
jtbandes at gmail.com
Sun Jan 24 02:34:35 CST 2016
Good/important examples.
The problem here seems to be that "sin", "mean", "remainder", etc. read
nicely as noun phrases, but the guidelines would recommend -ed/-ing verb
forms in this case (methods with both mutating and nonmutating variants),
not noun phrases:
"*When a mutating method is described by a verb, name its nonmutating
counterpart according to the 'ed/ing' rule*."
...but we don't have a verb to which to apply -ed or -ing. ("sined"?
"meaned"? "remaindered"?)
I agree that "sinInPlace()", "meanInPlace()", "remainderInPlace()" seem to
work pretty well, but I'm aware that I'm drawing on experience with the old
names of sortInPlace(), subtractInPlace(), etc., and in fact this case is
worse because the first words aren't really verbs (you can't sine something *in
place* any more than you can sine it). "takeSine()" doesn't sound great
either.
One option is to simply not offer mutating versions of these methods; then
users can write "y=y.remainder()" with only two extra characters (four with
spaces). IMO this is awkward; it also kinda necessitates an
isUniquelyReferenced check to avoid unnecessary copying.
Jacob "no useful suggestions to see here" Bandes-Storch
On Sat, Jan 23, 2016 at 11:36 PM, Tyler Fleming Cloutier via
swift-evolution <swift-evolution at swift.org> wrote:
> This is a very real problem. It has come up a nontrivial number of times
> during my attempt to conform Surge <https://github.com/mattt/Surge> to
> the API Guideline. My work in progress version is here
> <https://github.com/TheArtOfEngineering/Jolt>.
>
> 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.
>
> Thus I have three different types of API end points.
>
> - Global functions
> - Non-mutating methods
> - Mutating methods
>
> 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.
>
> 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.
>
> The global function is called `add`, the mutating method is called `add`,
> and the non-mutating method is called `adding`.
> add(x, y) vs x.add(y) vs x.adding(y)
>
> Excellent.
>
> 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.
>
> sum(myVec) vs myVec.sum() // <- this is non-mutating
>
> So far, acceptable.
>
> What about the function `sin`?
>
> Again, the global function is just `sin`. How, though, do you distinguish
> the mutating and non-mutating methods?
>
> sin(x) vs x.sin() vs x.sined()?
>
> 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.
>
> What about functions that are almost always abbreviated by convention like
> `ceil`?
>
> ceil(x) vs x.ceil() vs x.ceiled()
>
> In this case the InPlace prefix can save us. x.ceilInPlace() would work.
>
> Another good one is `remainder`.
>
> remainder(x) vs x.remainder() vs x.remaindered() ?
>
> 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.
>
> e.g.
> reciprocal
> threshold
> floor
> abs -> ???
> exp -> x.exponentiated()?
> exp2 or expSquared
> logb
> mean
> dot
> cross
>
> 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.
>
> 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.
>
> For example.
>
> let y = [...]
> let x = y.remainder()
>
> vs
>
> var y = […]
> y.remainder()
>
> I hope this helps to give a little bit of color on a real world example
> outside of the standard library.
>
> Thanks,
>
> Tyler
>
>
> On Jan 23, 2016, at 11:00 AM, Dave Abrahams via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> on Fri Jan 22 2016, Joe Groff <swift-evolution at swift.org> wrote:
>
> On Jan 22, 2016, at 1:57 PM, Jeff Kelley via swift-evolution
> <swift-evolution at swift.org> wrote:
>
> On Jan 22, 2016, at 4:53 PM, Joe Groff via swift-evolution
> <swift-evolution at swift.org
>
>
> <mailto:swift-evolution at swift.org <swift-evolution at swift.org>>>
> wrote:
>
> How do you handle naming non-mutating versions of these operations?
> Conjugating other irregular verbs also imposes a barrier on
> developers whose first language is not English.
>
>
> Swift could use “after” as a prefix, or something similar.
>
> array.sort()
> array.afterSort()
>
> I was tempted to say “afterSorting()” but that has the same problems
> mentioned above.
>
>
> That's reminiscent of the way the classic Cocoa naming guidelines
> cleverly avoided these issues by using the 'did-' prefix consistently
> instead of ever conjugating verbs into preterite tense. 'after' is a
> bit awkward, though, as are any other equivalent prefixes i can think
> of that have the same effect on the past participle (havingSplit?
> bySplitting?)
>
>
> "splitting" works perfectly well on its own, IMO. If there's an
> argument to the method, you'll want some kind of preposition like "At"
> or "On" afterwards.
>
> I think the real problem cases for this guideline as written are the
> ones where there's no underlying verb, like "union", or where the verb
> already has a strong non-mutating connotation, like "exclusiveOr."
> Those are the ones that really cry out for a different convention, like
> "InPlace."
>
> In developing the guidelines, we had some internal arguments about
> whether it was worth adding complexity to accomodate those cases, or
> whether we should simply not mention them and let them get sorted out on
> a case-by-case basis when they come up in code review. We didn't reach
> consensus, so this would be a useful area in which to get community
> input.
>
> --
> -Dave
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160124/26047fe9/attachment.html>
More information about the swift-evolution
mailing list