Issues with 0005-Better Translation of Objective-C APIs Into Swift

The following version of the API is significantly more clear with no
requirement of the variable names to be matched to the expectations of

the API signature:

let next = current.updating(proximity: p)

Either of these, IMO, clarify that API much better:

let next = current.replacingProximityWith(p)
let next = current.settingProximityTo(p)

but so what? The example started with a poor API; there are any number
of things one could do to improve it.

The point was to highlight that the clarity should be coming from the
API, not the inputs to the API.

I don't think anyone disagrees with that. I do think if you imagine that
the inputs to the method are actively misleading you can make its name
arbitrarily complex in order to counteract that, which would ultimately
hurt the readability of real code that generally isn't maliciously
named.

Similarly,

let content = listItemView.text.trimming(characters: .whitespaceAndNewlines)

At least I have some context at the call site what the purpose of
.whitespaceAndNewlines.

You wouldn't say "go to the garden and trim the plant: rhododendrons".
It isn't necessary for comprehension. Why do you feel characters: is
necessary here?

Because unlike the English phrase, "trimming" does not have an
implicit object set based on the context of a string; what else would
you typically trim in a garden other than plant life?

What else would you trim from a string than characters? I don't get the
difference.

I could naturally create an API that allows trimming by a line range
or string content, as an example.

"public func foo() {}".trimmed(text: "public ")
longContentWithKnownPreamble.trimmed(lines: 0..<5)

We could make these different APIs as opposed to overloads, though I'm
not convinced that they are not simply different ways to trim content.

I'm sure they *are* different ways to trim content.

I can't understand using "trimmed" the way you have above; it seems to
actively fight with the English language and does not strike me as clear.

···

on Tue Feb 02 2016, David Owens II <swift-evolution@swift.org> wrote:

On Feb 2, 2016, at 4:54 PM, Dave Abrahams via swift-evolution >> <swift-evolution@swift.org> wrote:

--
-Dave

That's not relying on well named inputs; it's relying on context, and
*that* is perfectly alright. We are never going to get to the point
that you can do without context in reading code. Proof: there's no
label for the receiver, yet you're not complaining. is

      v.text.trimming(characters: s)

somehow perfectly clear when

      listItemView.text.trimming(s)

is not?

···

on Wed Feb 03 2016, Gwendal Roué <gwendal.roue-AT-gmail.com> wrote:

Le 3 févr. 2016 à 01:54, Dave Abrahams via swift-evolution >> <swift-evolution@swift.org> a écrit :

on Tue Feb 02 2016, David Owens II <swift-evolution@swift.org> wrote:

On Feb 2, 2016, at 12:48 PM, Jarod Long via swift-evolution >>>> <swift-evolution@swift.org> wrote:

This is definitely more clear when you completely separate these
lines from their context, but code isn't written or read in complete
isolation like this, so I think these examples significantly
exaggerate the ambiguity of the pattern in the real world.

Even if you only make the minor change of renaming p to proximity
(which is really what it should be), the first example becomes
pretty clear:

let next = current.updating(proximity)

I just want to comment on this as I keep seeing this for arguments on
the lists. APIs themselves should not be relying on well named inputs
into them to create clear API signatures.

I don't think *anybody* on this list believes they should.

[…]

Similarly,

let content = listItemView.text.trimming(characters: .whitespaceAndNewlines)

At least I have some context at the call site what the purpose of
.whitespaceAndNewlines.

You wouldn't say "go to the garden and trim the plant: rhododendrons".
It isn't necessary for comprehension. Why do you feel characters: is
necessary here?

Precisely because of what you stated a few lines above : "I don't
think *anybody* on this list believes [API] should [be relying on well
named inputs »:

  let s: NSCharacterSet = .whitespaceAndNewlines
  let content = listItemView.text.trimming(s) // what?

--
-Dave

You wouldn't say "go to the garden and trim the plant: rhododendrons".
It isn't necessary for comprehension. Why do you feel characters: is
necessary here?

Precisely because of what you stated a few lines above : "I don't
think *anybody* on this list believes [API] should [be relying on well
named inputs »:

  let s: NSCharacterSet = .whitespaceAndNewlines
  let content = listItemView.text.trimming(s) // what?

That's not relying on well named inputs; it's relying on context, and
*that* is perfectly alright. We are never going to get to the point
that you can do without context in reading code. Proof: there's no
label for the receiver, yet you're not complaining. is

     v.text.trimming(characters: s)

somehow perfectly clear when

     listItemView.text.trimming(s)

is not?

Well, Dave, despite all your efforts to make points, one version requires more context than the other, and is thus less clear.

You are in the brevity team, that’s pretty clear. I’m quite happy that the brevity team exists and is powerful, because that team has already done a great job. `a + [1]` is so much better to the eye than `[a arrayByAddingObject:@1]`.

Yet… maybe the brevity team should not win everything, leaving both code and people exhausted.

Gwendal

Back to Strunk & White. Yes, people often use more words than
necessary, so it sounds normal. These two aren't so bad, but it's death
by a thousand cuts.

···

on Tue Feb 02 2016, Jordan Rose <swift-evolution@swift.org> wrote:

On Feb 2, 2016, at 17:28, David Owens II via swift-evolution >> <swift-evolution@swift.org> wrote:

On Feb 2, 2016, at 4:54 PM, Dave Abrahams via swift-evolution > >>> <swift-evolution@swift.org >>> <mailto:swift-evolution@swift.org>> >>> wrote:

Similarly,

let content = listItemView.text.trimming(characters: .whitespaceAndNewlines)

At least I have some context at the call site what the purpose of
.whitespaceAndNewlines.

You wouldn't say "go to the garden and trim the plant: rhododendrons".
It isn't necessary for comprehension. Why do you feel characters: is
necessary here?

Because unlike the English phrase, "trimming" does not have an
implicit object set based on the context of a string; what else
would you typically trim in a garden other than plant life? I could
naturally create an API that allows trimming by a line range or
string content, as an example.

"public func foo() {}".trimmed(text: "public ")
longContentWithKnownPreamble.trimmed(lines: 0..<5)

We could make these different APIs as opposed to overloads, though
I'm not convinced that they are not simply different ways to trim
content.

That's actually why this one is "trimming", not "trimmed". "trimming"
allows a direct object; "trimmed" does not.

I don't really have a problem with this overload set, although
admittedly I can't tell if we're trimming prefixes, suffixes, or both,
and I would hope that's consistent between the two.

inputText.trimming(.whitespaceAndNewlines)
inputText.trimming("public ")

These are both perfectly good noun phrases in English, too: "[get me]
the inputText, trimming whitespace and newlines" and "[get me] the
inputText, trimming 'public '".

(But to play David's Advocate, it also seems perfectly reasonable in
English to say "[get me] the inputText, trimming whitespace and
newline characters" and "[get me] the inputText, trimming the string
'public '".)

--
-Dave

No, really, I'm in the clarity team. The same rules that go for English
go here. Clarify what's ambiguous, or that you can't easily get from
context. Clarifying things that are readily available from context just
makes code/prose/whatever *less* clear.

It is true that you can't know what context an API will be used in.
Does that mean you should preemptively build in as many clarifications
as possible in case the context leaves usage unclear? IMO, no. If each
of our words came pre-loaded with clarification, it would make ordinary
sentences unmanageable.

The author of an API cannot guarantee clarity at the use-site. The best
she can do is to provide the user of the API with the tools needed to
make use-sites clear. But part of that is a responsibility not to force
detail into the use-site that isn't going to be helpful in most cases.

···

on Wed Feb 03 2016, Gwendal Roué <gwendal.roue-AT-gmail.com> wrote:

You wouldn't say "go to the garden and trim the plant: rhododendrons".
It isn't necessary for comprehension. Why do you feel characters: is
necessary here?

Precisely because of what you stated a few lines above : "I don't

think *anybody* on this list believes [API] should [be relying on well
named inputs »:

  let s: NSCharacterSet = .whitespaceAndNewlines
  let content = listItemView.text.trimming(s) // what?

That's not relying on well named inputs; it's relying on context, and
*that* is perfectly alright. We are never going to get to the point
that you can do without context in reading code. Proof: there's no
label for the receiver, yet you're not complaining. is

     v.text.trimming(characters: s)

somehow perfectly clear when

     listItemView.text.trimming(s)

is not?

Well, Dave, despite all your efforts to make points, one version
requires more context than the other, and is thus less clear.
You are in the brevity team, that’s pretty clear.

--
-Dave

Well, I won’t be very wrong if I say that Cocoa APis have often been praised for their clarity, despite the fact that they are all but terse :-)

Gwendal

···

Le 3 févr. 2016 à 19:46, Dave Abrahams <dabrahams@apple.com> a écrit :

on Wed Feb 03 2016, Gwendal Roué <gwendal.roue-AT-gmail.com> wrote:

You wouldn't say "go to the garden and trim the plant: rhododendrons".
It isn't necessary for comprehension. Why do you feel characters: is
necessary here?

Precisely because of what you stated a few lines above : "I don't

think *anybody* on this list believes [API] should [be relying on well
named inputs »:

  let s: NSCharacterSet = .whitespaceAndNewlines
  let content = listItemView.text.trimming(s) // what?

That's not relying on well named inputs; it's relying on context, and
*that* is perfectly alright. We are never going to get to the point
that you can do without context in reading code. Proof: there's no
label for the receiver, yet you're not complaining. is

    v.text.trimming(characters: s)

somehow perfectly clear when

    listItemView.text.trimming(s)

is not?

Well, Dave, despite all your efforts to make points, one version
requires more context than the other, and is thus less clear.
You are in the brevity team, that’s pretty clear.

No, really, I'm in the clarity team.

I'm not necessarily in the brevity team myself, but I really enjoy the changes in the proposal. Swift still stays more verbose and clearer than a lot of languages that don't have argument labels.

···

On 03 Feb 2016, at 18:21, Gwendal Roué via swift-evolution <swift-evolution@swift.org> wrote:

Yet… maybe the brevity team should not win everything, leaving both code and people exhausted.

And now it'll be death by a thousand command-clicks. :)

···

On Tue, Feb 2, 2016 at 7:59 PM, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

on Tue Feb 02 2016, Jordan Rose <swift-evolution@swift.org> wrote:

>> On Feb 2, 2016, at 17:28, David Owens II via swift-evolution > >> <swift-evolution@swift.org> wrote:
>>
>>
>>> On Feb 2, 2016, at 4:54 PM, Dave Abrahams via swift-evolution > > > >>> <swift-evolution@swift.org > >>> <mailto:swift-evolution@swift.org>> > >>> wrote:
>>>
>>>> Similarly,
>>>>
>>>> let content = listItemView.text.trimming(characters:
.whitespaceAndNewlines)
>>>>
>>>> At least I have some context at the call site what the purpose of
>>>> .whitespaceAndNewlines.
>>>
>>> You wouldn't say "go to the garden and trim the plant: rhododendrons".
>>> It isn't necessary for comprehension. Why do you feel characters: is
>>> necessary here?
>>
>> Because unlike the English phrase, "trimming" does not have an
>> implicit object set based on the context of a string; what else
>> would you typically trim in a garden other than plant life? I could
>> naturally create an API that allows trimming by a line range or
>> string content, as an example.
>>
>> "public func foo() {}".trimmed(text: "public ")
>> longContentWithKnownPreamble.trimmed(lines: 0..<5)
>>
>> We could make these different APIs as opposed to overloads, though
>> I'm not convinced that they are not simply different ways to trim
>> content.
>
> That's actually why this one is "trimming", not "trimmed". "trimming"
> allows a direct object; "trimmed" does not.
>
> I don't really have a problem with this overload set, although
> admittedly I can't tell if we're trimming prefixes, suffixes, or both,
> and I would hope that's consistent between the two.
>
> inputText.trimming(.whitespaceAndNewlines)
> inputText.trimming("public ")
>
> These are both perfectly good noun phrases in English, too: "[get me]
> the inputText, trimming whitespace and newlines" and "[get me] the
> inputText, trimming 'public '".
>
> (But to play David's Advocate, it also seems perfectly reasonable in
> English to say "[get me] the inputText, trimming whitespace and
> newline characters" and "[get me] the inputText, trimming the string
> 'public '".)

Back to Strunk & White. Yes, people often use more words than
necessary, so it sounds normal. These two aren't so bad, but it's death
by a thousand cuts.
<https://lists.swift.org/mailman/listinfo/swift-evolution&gt;