[swift-evolution] When to use argument labels (a new approach)
Dave Abrahams
dabrahams at apple.com
Wed Feb 3 19:24:25 CST 2016
on Wed Feb 03 2016, Radosław Pietruszewski <swift-evolution at swift.org> wrote:
> By the way. I know this isn’t the main topic for the thread, but I
> would adding back a shortcut syntax for making a variable name the
> external label. It’s tiring to have to write:
>
> methodName(moreThanTwoWords moreThanTwoWords: Type) // exaggerated for dramatic effect.
>
> Most methods, in my experience, still don’t need a label for the first
> argument, but in the ones that do, we shouldn’t penalize doing so with
> ugly repetitiveness.
The easiest way to solve this would be to change the default for first
argument labels, but I really don't want to touch that in this thread.
However, I will refer to something Joe Groff points out in
<http://article.gmane.org/gmane.comp.lang.swift.evolution/4096>: the
automatic argument-name-matches-label default you're getting may not
actually be serving the authors of well-written APIs.
> (The Q is what syntax should do this. The old “#argument” obviously
> feels wrong, as “#” is otherwise reserved as “macro-like, or
> compiler-generated”.)
>
> — Radek
>
>> On 03 Feb 2016, at 01:32, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
>>
>>
>> This thread is related to the review of new API guidelines, but it's not
>> a review thread; it's exploratory. The goal is to come up with
>> guidelines that:
>>
>> * describe when and where to use argument labels
>> * require labels in many of the cases people have asked for them
>> * are understandable by humans
>> * preserve important semantics communicated by existing APIs.
>>
>> Here's what I'm thinking
>>
>> 1. If and only if the first argument could complete a sentence*
>> beginning in the base name and describing the primary semantics of
>> the call, it gets no argument label:
>>
>> a.contains(b) // b completes the phrase "a contains b"
>> a.mergeWith(b) // b completes the phrase "merge with b"
>>
>> a.dismiss(animated: b) // "a, dismiss b" is a sentence but
>> // doesn't describe the semantics at all,
>> // thus we add a label for b.
>>
>> a.moveTo(x: 300, y: 400) // "a, move to 300" is a sentence
>> // but doesn't describe the primary
>> // semantics, which are to move in both
>> // x and y. Thus, x gets a label.
>>
>> a.readFrom(u, ofType: b) // "a, read from u" describes
>> // the primary semantics, so u gets no
>> // label. b is an
>> // option that tunes the primary
>> // semantics
>>
>> [Note that this covers all the direct object cases and, I believe,
>> all the default argument cases too, so maybe that exception can be
>> dropped. We still need the exceptions for full-width type
>> conversions and indistinguishable peers]
>>
>> Note: when there is a noun in the base name describing the role of the
>> first argument, we skip it in considering this criterion:
>>
>> a.addObserver(b) // "a, add b" completes a sentence describing
>> // the semantics. "Observer" is omitted in
>> // making this determination.
>>
>> * We could say "clause" here but I think making it an *independent*
>> clause doesn't rule out any important use-cases (see
>> https://web.cn.edu/kwheeler/gram_clauses_n_phrases.html) and at that
>> point, you might as well say "sentence," which is a more
>> universally-understood term.
>>
>> 2. Words that describe attributes of an *already-existing* instance
>> should go in the base name rather than in a label:
>>
>> a.tracksHavingMediaType("Wax Cylinder") // yes
>> a.removeFirstTrackHavingMediaType("BetaMax") // yes
>>
>> a.tracks(mediaType: "Wax Cylinder") // no
>> a.removeFirstTrack(havingMediaType: "BetaMax") // no
>>
>> [yes, we could use "With" instead of "Having", but it's more
>> ambiguous]
>>
>> Words that describe attributes of an instance *to be created* should
>> go in argument labels, rather than the base name (for parity with
>> initializers):
>>
>> AudioTrack(mediaType: "BetaMax") // initializer
>> trackFactory.newTrack(mediaType: "Wax Cylinder") // yes
>>
>> trackFactory.newTrackWithMediaType("Wax Cylinder") // no
>>
>> 3. (this one is separable) When the first argument is the *name* or
>> *identifier* of the subject in the base name, do not label it or
>> describe it in the base name.
>>
>> a.transitionToScene(.GreatHall) // yes
>> a.transitionToSceneWithIdentifier(.GreatHall) // no
>>
>> let p = someFont.glyph("propellor") // yes
>> let p = someFont.glyphWithName("propellor") // no
>> let p = someFont.glyph(name: "propellor") // no
>>
>> Thoughts?
>>
>> --
>> -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
--
-Dave
More information about the swift-evolution
mailing list