[swift-evolution] When to use argument labels (a new approach)
plx
plxswift at icloud.com
Thu Feb 4 18:39:19 CST 2016
> On Feb 4, 2016, at 1:47 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
>>
>
> s.find(subString, .ignoringCase | .ignoringDiacriticalMarks) -> Range<String.Index>
>
>> func trimming(characterSet: NSCharacterSet) -> String func
>
> s.trimming(.whitespaceAndNewlines)
>
> Gah; you're right, here. Keeping a linguistic basis requires backing
> off all the way from “sentence” to “phrase.” That's actually where I
> started with this guideline, but thought I'd be able to strengthen it.
> Saying “sentence or noun phrase” (if it works) might be better than just
> “phrase” because “noun phrase” is always a term of art, whereas “phrase”
> might just be interpreted casually.
I think sentence-or-noun-phrase covers things “linguistically", but it seems to carve out a pretty territory; other than special-cases (init, operators, label-less functions like `min`), I can’t think of anything that would be:
- reasonably-named (e.g. a name you’d actually want to use)
- *not* satisfying the proposed sentence-or-noun-phrase rule
…is there a good example of such?
Even if that’s right I’m not sure it’s a bad thing, but it’s still broad enough to give me a little pause; it may actually be the easiest way to carve out the non-init, non-operator, non-label-free-functions.
>> …than to win an argument over whether or not “add observer” describes
>> *enough* of the “primary semantics” of this method to fall under the
>> proposed guideline.
>
> That seems less ambiguous to me than primary focus, and I believe a few
> examples in the guidelines would be enough to settle most debates.
Fair enough. There’s still a subtle ambiguity in "primary semantics” (is it primary in the sense of “describing the most-important part" of the semantics, or is it “primary semantics” in the sense of “describes the majority/most(/etc.) of the semantics”), but examples should be enough to clear it up.
>
>>
>>
>> But that’s just an opinion, and on reflection I don’t think “primary
>> semantic focus” is the clearest formulation, either; I just don’t have
>> anything better.
>>
>>>
>>>> This rule seems to cover e.g. `addObserver(_:forKeyPath:)` and
>>>> `addObserver(_:selector:name:object:)` and `encodeObject(_:forKey:)`
>>>> and `present(_:animated:completion:)` (née
>>>> `presentViewController(_:animated:completion:)`), and so on.
>>>>
>>>> A point to bring up is that under these rules, the “evolution” of a
>>>> name would be different: the just-so story for how
>>>> `addObserver(_:forKeyPath:)` came to be so-called is that it *began*
>>>> as `add(observer:forKeyPath:)`, but b/c the `observer` argument is the
>>>> semantic focus it "made sense to move `observer` into the method
>>>> name”; that is, the assumption is that functions like
>>>> `addObserver(_:forKeyPath:)` are considered to be exceptions to the
>>>> "base convention” and need to be justified.
>>>
>>> Okay, I understand it, but I'm not sure why it's better. Please explain
>>> why this is an improvement over the other approach.
>>>
>>>> Also note that "counter-examples" to rule (a) are anything for which
>>>> no one argument is easily-identifiable as the semantic focus.
>>>>
>>>> EG, in a function like:
>>>> `adjudicate(plaintiff:defendant:circumstances:)` we can colorably
>>>> claim `circumstances` is a modifier-type parameter, but we don’t—and
>>>> shouldn’t!—treat either `plaintiff` or `defendant` as the
>>>> semantic-focus. If you have two focuses then you have no focus, as it
>>>> were.
>>>>
>>>> For (b), the intuition is that whenever argument-order is irrelevant,
>>>> arguments should be unlabelled; thus e.g.:
>>>>
>>>> - min/max: don’t label the arguments
>>>> - hypot: don’t label the arguments
>>>> - copysign: ideally, label the arguments
>>>> - atan2: ideally, label the arguments
>>>
>>> Those last two may draw some quibbles from the math domain experts, but
>>> I agree with the spirit.
>>>
>>>>
>>>> …and so on. Note that these examples are all "free functions”; there
>>>> don’t seem to be many natural examples that *aren’t* free
>>>> functions.
>>>
>>> colorMixer.blend(color1, color2)
>>> track.fade(from: initialVolume, to: targetVolume)
>>>
>>>
>>>> Also, please don’t be mislead by your familiarity with
>>>> e.g. `copysign` and/or `atan2`; they are used here to illustrate a
>>>> general principle (argument-ordering) only, but in practice such
>>>> highly-familiar “legacy functions” might be best-off given
>>>> special-case handling.
>>>
>>> Right, so we'd want different examples.
>>>
>>>> ### III. Naming Functions/Ecosystem Rule
>>>>
>>>> The previous sections essentially assumed the function names are
>>>> already-chosen (in line with existing conventions) and voice specific
>>>> argument-labeling preferences.
>>>>
>>>> This section deals with a few changes to how function names should be chosen.
>>>>
>>>> The over-arching consideration is what I’ve been calling the
>>>> “Ecosystem rule”: whenever a method a member of a “method family"—or
>>>> could foreseeably become a member of such—one should aim for
>>>> consistency in the base name, and use argument-labels as necessary;
>>>> note that method families need not *require* argument labels:
>>>>
>>>> `contains(_: Point)`
>>>> `contains(_: Line)`
>>>> `contains(_: Shape)`
>>>>
>>>> …but they *may* require them, as for example in the `login` function
>>>> that has already been discussed.
>>>>
>>>> The “ecosystem-rule" can also be applied somewhat more-broadly;
>>>> consider the following name suggestions:
>>>>
>>>> `animate(duration:animations:)`
>>>> `animate(duration:animations:completion:)`
>>>> `animate(duration:delay:options:animations:completion:)`
>>>> `animateUsingKeyFrames(duration:delay:options:animations:completion:)`
>>>> `animateUsingSpring(duration:delay:damping:initialVelocity:options:animations:completion:)`
>>>>
>>>> …where the first three form an obvious family, and the next two are
>>>> obvious “cousins” of that family due to choice of base names.
>>>>
>>>> A corollary of this policy is that the rule (3) suggestion—of omitting
>>>> something like `…ForIdentifier...` or `(forIdentifier:…)`—will
>>>> sometimes be overruled out of ecosystem concerns, but I suspect this
>>>> will be somewhat rare in practice.
>>>>
>>>> For example, consider the following naming suggestions for the “tracks” example:
>>>>
>>>> // solo method (not part of any family)
>>>> asset.trackWith(trackID)
>>>>
>>>> // family
>>>> asset.allTracksWith(mediaCharacteristic: …)
>>>> asset.allTracksWith(mediaType: ...
>>>>
>>>> // the below, instead of `trackWith` or `track(
>>>> asset.firstTrackWith(mediaCharacteristic: ...)
>>>> asset.firstTrackWith(mediaType: …)
>>>>
>>>> …or the same again, but perhaps dropping the `With` if that’s the overall preference.
>>>>
>>>> In any case, the overall goal behind the "ecosystem rule” is that
>>>> similar things should be named similarly, and when semantic
>>>> differences are small-enough it makes sense to use argument labels to
>>>> make distinctions; different base names should be for functions that
>>>> are at least a little different from each other.
>>>
>>> This “rule” seems pretty darned vague, even after all this explanation.
>>> I don't see how it could possibly be stated succinctly,
>>>
>>> Furthermore, as I wrote to Erica, I have concerns about anything that
>>> gives special treatment to method families, specifically:
>>>
>>> * I'm wary of adding anything that encourages the creation of
>>> “method families,” which have a higher cognitive overhead than many of
>>> the alternatives.
>>> * A guideline that forces you to change an existing non-overloaded API,
>>> just because you are adding an overload, is problematic.
>>
>> Understood, and noted, so I won’t press it, other than to point out
>> that method families have come up independently a few times, which may
>> deserve some consideration.
>>
>> My own sense is they are rather more common in application-level code
>> than would be ideal in standard library code.
>
> They do occur. I want them to look/feel good. I just don't want to
> make special rules for them, if possible. Let's try to come up with
> guidelines that work for everything with fewer exceptions.
>
> --
> -Dave
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list