[swift-evolution] When to use argument labels (a new approach)

Dave Abrahams dabrahams at apple.com
Wed Feb 3 18:56:47 CST 2016


on Wed Feb 03 2016, Charles Constant <swift-evolution at swift.org> wrote:

> I find arguments with prepositions easier to read, on the whole, even when
> they're not strictly necessary.
>

Hi Charles,

FWIW, your personal style notwithstanding, we *are* standardizing on
camelCase, and CamelCase (for types), so writing your examples that way
would help us evaluate them as useful for the guidelines.

> Even though, this code makes sense:
>
> *     a.move_to( b )*
>
> *     draw_line( origin: b, conclusion: c )*
>
> I'd prefer to see this:
>
> *     a.move( to_point: b )*

The difference between this and the first example isn't a preposition;
it's a (IMO needless) noun.  What point (NPI) are you trying to
illustrate?

> *     draw_line( from_point: b, to_point: c )*
>
> Similarly, for the example "*a.read_from( u, of_type: b )*" I find this
> easier to read:
>
> *     a.read( from_url: u, from_type: b)*

The difference here is just in your *choice* of preposition.

> Which makes it easier to understand if it's followed by:
>
> *     a.read( from_url: u, to_type: b)*
>
> I find it helpful in my own code. Having said that, I'm not sure if it
> would suit huge multi-person projects, since it leads to a lot of similarly
> named functions.

I don't see how, but then I can't pick out any regularity in what you're
suggesting so I don't really know how to evaluate it.

>
> On Tue, Feb 2, 2016 at 4:32 PM, 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