[swift-evolution] When to use argument labels, part DEUX (was: when to use argument labels (a new approach))

plx plxswift at icloud.com
Sat Feb 6 09:01:09 CST 2016

I like these revisions quite a bit.

> On Feb 5, 2016, at 3:32 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> Given all the awesome feedback I've gotten on this thread, I went back
> to the drawing board and came up with something new; I think this one
> works.  The previously-stated goals still apply:
> * describe when and where to use argument labels
> * require labels in many of the cases people have asked for them
> * are understandable by humans (this means relatively simple)
> * preserve important semantics communicated by existing APIs.
> Please keep in mind that it is a non-goal to capture considerations we
> think have a bearing on good names (such as relatedness of parameters):
> it's to create simple guidelines that have the right effect in nearly
> all cases.
> A. When arguments can't be usefully distinguished from one another, none
>   should have argument labels, e.g. min(x,y), zip(x,y,z).  
> B. Otherwise,
>  1. At the call site, a first parameter that has no argument label must
>     form part of a grammatical phrase that starts with the basename, less
>     any trailing nouns.  
>       print(x)
>       a.contains(b)
>       a.mergeWith(b)
>       a.addGestureRecognizer(x)
>            ^~~~~~~~~~~~~~~~~ trailing noun
>     This phrase must have the correct semantic implications, so, e.g.
>       a.dismiss(b)           // no, unless a is really dismissing b
>       a.dismissAnimated(b)   // no, not grammatical
>       a.dismiss(animated: b) // yes, using a label
>  2. If the first argument is part of a prepositional phrase, put the
>     parenthesis immediately after the preposition. 
>       a.encodeWith(b)
>       a.moveFrom(b, to: c)
>     Thus, if words are required for any reason between the preposition
>     and the first argument, they go into the first argument label.
>       a.tracksWith(mediaType: b, composer: c)
>       a.moveTo(x: 22, y: 99)
> Notes: 
> a. I would recommend prepositions other than "with" in nearly all
>   cases, but that's not the point of these rules.
> b. I can understand the aesthetic appeal of
>    a.move(from: b, to: c)

I agree with the aesthetic and also not wanting to complicate the rules to cover it. 

I also think this is a bad example, though, b/c in practice one would *hope* that such calls would look more like:

container.move(element, from: currentIndex, to: destinationIndex)

…and whatnot; I suspect that the `move(from:to:)` case may be getting strong reactions in part b/c it’s actually an unusually-poorly-named method to begin with.

Also, as these are just guidelines, in third party code we can deviate from them (at our own peril, but we can...).

>   but I believe it is not a clear enough improvement to justify
>   additional complexity in the guidelines.
> Questions:
> 1. I'm not expecting these guidelines to make everybody optimally happy,
>   all the time, but they shouldn't be harmful.  Are there any cases for
>   which they produce results you couldn't live with?
> 2. Are there any cases where you'd be confused about how to apply these
>   guidelines?

I do find some of the rules worded in ways that are hard to apply in the presence of trailing nouns; I’m not sure the guidelines are strong enough here to force the “right” outcome.

Consider this example:

// not-intended: 
a.tracksWithMediaCharacteristic(b, composer: c)

…applying our guidelines:

- `tracks with media characteristic b` is a grammatical phrase
- `tracks with b` is (arguably also) a grammatical phrase
- `b` is “part of” the "noun phrase" "tracks with media characteristic b"
- `b` is “part of” the “prepositional phrase” “with media characteristic b"

…and although I think this is fine under a “strict” application of the guidelines—as `b` is part of a prepositional phrase, we *must* split the base name after the preposition, at which point we are allowed to “restore" the `mediaCharacteristic:` label if we wish—I don’t know in practice that the “strict” interpretation will be what people naturally opt to use.

Taking it from the other direction, the way the guidelines are phrased I worry bit that you wind up with:

// not intended
a.add(subview: v) (or add(v)) // instead of `a.addSubview(v)`
a.add(layoutGuide: g) (or add(g)) // instead of `a.addLayoutGuide(g)`
a.add(gestureRecognizer: r) (or add(r)) // instead of `a.addGestureRecognizer(r)`

…b/c the rule that we should ignore such trailing nouns means those are *exactly* as-grammatical as the “intended” imports (it’s “add v” vs “add v”, after all, under the guidelines), so at least within the proposed guidelines there’s no apparent reason to prefer the `addSubview` form vis-a-vis the `add(subview:)` (or `add(_)`) form(s).

Perhaps I just overlooked something from the non-label guidelines in this response, but it’d seem the omit-needless-words would also steer you towards `add()`, with or without a first-argument label.

So overall these guidelines seem more than adequate to resolve labeling disputes if we are already dealing with "well-named” functions but may be a bit weak to steer naming *decisions*.

But, for guidelines, that might still be OK?

> Thanks in advance for all your valuable input!
> P.S. Doug is presently working on generating new importer results, based
>     on these guidelines, for your perusal.  They should be ready soon.
> -- 
> -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