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


(Kevin Schlei) #1

I am strongly against the proposed changes to the translation of
Objective-C APIs. I think the changes promote terseness for terseness sake,
lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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


(Dave Abrahams) #2

I spent many years teaching programming, and It's not obvious to me.
How about spelling it out for the rest of us?

···

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

I am strongly against the proposed changes to the translation of
Objective-C APIs. I think the changes promote terseness for terseness sake,
lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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

--
-Dave


(Kevin Schlei) #3

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does.
In this case, it returns a new string instance. Where is that explained? In
the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What
does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all
the hints. But this line:

let next = current.locationByUpdatingProximity(p)

Lets you know that:

1. we're returning a *'location'*
2. '*by* *updating' *current with a new *'proximity'*

When is the last time you saw a gerund (-ing) as a method name? I wouldn't
let my students write that. Gerunds make good boolean properties. How would
you even read the first line above out loud? Probably by filling in the
words in the second line, magically.

My second major issue is that autocomplete grouping is totally lost when
dropping the type returned at the beginning of the call. How many of us
learned a *ton* when we just autocompleted .stringBy? Look at all the
things you can do! But by removing the 'useless word' (really don't like
that flag name) we have no grouping of constructor methods.

I see a lot of discussion on how to deal with 'with' and 'by' and other
words, but I want to strongly suggest that the current naming practices
provide context and clarity. It makes code readable and accessible. Don't
forget about when you didn't know how to code! These method names are
teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't
clarity be prioritized over brevity (where have I seen that...)

I can't put it better than another forums poster:

Does the Swift team seriously believe that systematically parsing and

···

extensively munging patterns in not-quite-natural-language is tractable to
support all the corner cases for? And that, even if it were, that it could
avoid confusion in less-than-perfect codebases? The idea that this will
somehow benefit a language, particularly one in which clear and obvious
bridging is so vital is *insane*. The best it can do is a reasonable job,
with some amount of either unfixable brokenness forced upon developers in
perpetuity, or constant churn stemming from perpetual fixing of brokenness.
Swift's translation is currently simple to reason about, and the language
as a whole has got a really great thing going on. I'm really happy with
where it is at this moment. Why ruin it by boneheadedly detonating the
utility of two years of progress in literature and the library of online
information about Swift? Seriously, why?

On Tue, Feb 2, 2016 at 1:04 PM, Kevin Schlei <kevinschlei@gmail.com> wrote:

I am strongly against the proposed changes to the translation of
Objective-C APIs. I think the changes promote terseness for terseness sake,
lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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


(Jarod Long) #4

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does. In this case, it returns a new string instance. Where is that explained? In the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all the hints. But this line:

I think it's only unclear because p is not a descriptive name (next and current aren't terribly helpful either), and we don't have any context or type information.

let next = current.locationByUpdatingProximity(p)

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)

Ultimately, I don't think this is a very difficult pattern to learn. Maybe the first handful of times you see it you'll need to read the documentation to know exactly what it's doing, but once you've seen it a few times, it's an instantly recognizable pattern. If you see a gerund method, it returns a new thing by doing the verb to the thing. Is it worth the redundancy and noise to save new developers from possibly needing to look at a method's documentation a few times?

I see the tradeoff here as a minor, essentially one-time decrease in clarity for new developers, and a small but indefinite increase in clarity for everyone else.

When is the last time you saw a gerund (-ing) as a method name? I wouldn't let my students write that. Gerunds make good boolean properties. How would you even read the first line above out loud? Probably by filling in the words in the second line, magically.

Not having used this pattern before isn't a valid reason to not start using it, and the API design guidelines already provide a fine pattern for boolean properties, so we don't need gerunds for them.

My second major issue is that autocomplete grouping is totally lost when dropping the type returned at the beginning of the call. How many of us learned a *ton* when we just autocompleted .stringBy? Look at all the things you can do! But by removing the 'useless word' (really don't like that flag name) we have no grouping of constructor methods.

I agree that this is kind of unfortunate, but I also don't think that it's a good idea to limit our API design for the sake of autocomplete discovery. Documentation is readily available and is a far better form of discovery since you don't just see things that start with the same prefix that you're using. The tradeoff is that you have to go out of your way to do it, but these are the kinds of good habits we should be teaching students.

···

On Feb 2, 2016, at 11:16, Kevin Schlei via swift-evolution <swift-evolution@swift.org> wrote:

I see a lot of discussion on how to deal with 'with' and 'by' and other words, but I want to strongly suggest that the current naming practices provide context and clarity. It makes code readable and accessible. Don't forget about when you didn't know how to code! These method names are teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't clarity be prioritized over brevity (where have I seen that...)

I can't put it better than another forums poster:

Does the Swift team seriously believe that systematically parsing and extensively munging patterns in not-quite-natural-language is tractable to support all the corner cases for? And that, even if it were, that it could avoid confusion in less-than-perfect codebases? The idea that this will somehow benefit a language, particularly one in which clear and obvious bridging is so vital is insane. The best it can do is a reasonable job, with some amount of either unfixable brokenness forced upon developers in perpetuity, or constant churn stemming from perpetual fixing of brokenness. Swift's translation is currently simple to reason about, and the language as a whole has got a really great thing going on. I'm really happy with where it is at this moment. Why ruin it by boneheadedly detonating the utility of two years of progress in literature and the library of online information about Swift? Seriously, why?

On Tue, Feb 2, 2016 at 1:04 PM, Kevin Schlei <kevinschlei@gmail.com <mailto:kevinschlei@gmail.com>> wrote:
I am strongly against the proposed changes to the translation of Objective-C APIs. I think the changes promote terseness for terseness sake, lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #5

Sorry for the premature send! Continuing:

Ah, thank you...

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

For a beginning programmer, there is no indication of what .trimming
does.

It trims. In this case, it trims whitespace and newlines. I think
that's actually pretty clear.

In this case, it returns a new string instance.

That isn't what it *does*; that's the type it returns.

Where is that explained? In the documentation. Nowhere near the method
call.

Exactly. You get this information from context. If you take some text
and you trim off the whitespace and newlines, you get some other text.

I don't believe that teaching students that the name of a method is
going to supply all the relevant type information is doing them a
service. This is *not* what they'll encounter in the real world,
not even if they're programming in Objective-C and using Cocoa.

So are we reduced now to looking up documentation just to read code? What
does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all
the hints.

It's 75% unclear because there's no context. I have no idea what
current or p are. But I *can* tell (assuming this is following the
guidelines), that the method returns a modified version of current that
is obtained by updating p (whatever that means).

But this line:

let next = current.locationByUpdatingProximity(p)

Lets you know that:

1. we're returning a *'location'*
2. '*by* *updating' *current with a new *'proximity'*

Under the proposed guidelines, that would be:

  let next = current.updatingProximityWith(p)

or

  let next = current.replacingProximityWith(p)

or

  let next = current.settingProximityTo(p)

When is the last time you saw a gerund (-ing) as a method name?

FWIW, these are not gerunds, they're present participles.

I wouldn't let my students write that. Gerunds make good boolean
properties. How would you even read the first line above out loud?
Probably by filling in the words in the second line, magically.

You're presuming that the guidelines as written would endorse that line,
but they don't. Clarity at the point of use is the prime directive.

My second major issue is that autocomplete grouping is totally lost when
dropping the type returned at the beginning of the call. How many of us
learned a *ton* when we just autocompleted .stringBy? Look at all the
things you can do! But by removing the 'useless word' (really don't like
that flag name) we have no grouping of constructor methods.

These things can be handled in other ways, e.g. by improving the tools,
without punishing readability at the use-site by adding needless words.

I see a lot of discussion on how to deal with 'with' and 'by' and other
words, but I want to strongly suggest that the current naming practices
provide context and clarity. It makes code readable and accessible. Don't
forget about when you didn't know how to code! These method names are
teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't
clarity be prioritized over brevity (where have I seen that...)

It is. You just have a different idea about what creates clarity in
source code. IMO, clarity is provided by communicating semantics, *not*
by repeating non-semantic details such as which specific types are in
use. By eliminating words that don't communicate semantics, you make
the semantics clearer. If we didn't believe in this approach, Swift
wouldn't have type inference.

HTH,

···

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

--
-Dave


(Aaron Crespo) #6

I think Kevin and I come from the same place and largely agree. I feel like
this is trading in of accessibility and discoverability for the sake of
terseness. This might be aesthetically pleasing but gives up many positive
side effects the more descriptive names provide.

Consider the time before you knew you could or how to "check the
documentation". Or the time spent scanning unfamiliar or long forgotten
code.

These concerns might be eased if consideration was also being given to the
first parameter rule. And the (now) odd difference between initializers and
function parameter names. Apply the same rules as any parameter name.

Stealing Kevins example:

let next = current.updating(proximity: p)

Not great but better.

···

On Tue, Feb 2, 2016 at 2:16 PM, Kevin Schlei via swift-evolution < swift-evolution@swift.org> wrote:

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does.
In this case, it returns a new string instance. Where is that explained? In
the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What
does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all
the hints. But this line:

let next = current.locationByUpdatingProximity(p)

Lets you know that:

1. we're returning a *'location'*
2. '*by* *updating' *current with a new *'proximity'*

When is the last time you saw a gerund (-ing) as a method name? I wouldn't
let my students write that. Gerunds make good boolean properties. How would
you even read the first line above out loud? Probably by filling in the
words in the second line, magically.

My second major issue is that autocomplete grouping is totally lost when
dropping the type returned at the beginning of the call. How many of us
learned a *ton* when we just autocompleted .stringBy? Look at all the
things you can do! But by removing the 'useless word' (really don't like
that flag name) we have no grouping of constructor methods.

I see a lot of discussion on how to deal with 'with' and 'by' and other
words, but I want to strongly suggest that the current naming practices
provide context and clarity. It makes code readable and accessible. Don't
forget about when you didn't know how to code! These method names are
teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't
clarity be prioritized over brevity (where have I seen that...)

I can't put it better than another forums poster:

Does the Swift team seriously believe that systematically parsing and

extensively munging patterns in not-quite-natural-language is tractable to
support all the corner cases for? And that, even if it were, that it could
avoid confusion in less-than-perfect codebases? The idea that this will
somehow benefit a language, particularly one in which clear and obvious
bridging is so vital is *insane*. The best it can do is a reasonable
job, with some amount of either unfixable brokenness forced upon developers
in perpetuity, or constant churn stemming from perpetual fixing of
brokenness. Swift's translation is currently simple to reason about, and
the language as a whole has got a really great thing going on. I'm really
happy with where it is at this moment. Why ruin it by boneheadedly
detonating the utility of two years of progress in literature and the
library of online information about Swift? Seriously, why?

On Tue, Feb 2, 2016 at 1:04 PM, Kevin Schlei <kevinschlei@gmail.com> > wrote:

I am strongly against the proposed changes to the translation of
Objective-C APIs. I think the changes promote terseness for terseness sake,
lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Owens II) #7

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.

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)

Similarly,

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

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

Ultimately, I don't think this is a very difficult pattern to learn. Maybe the first handful of times you see it you'll need to read the documentation to know exactly what it's doing, but once you've seen it a few times, it's an instantly recognizable pattern. If you see a gerund method, it returns a new thing by doing the verb to the thing. Is it worth the redundancy and noise to save new developers from possibly needing to look at a method's documentation a few times?

I really do not like the -ing form; it reads backwards. I intuitively expected the object of the “trimming” to be the parameters, not the instance invoking the method.

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

Whereas when I read the above, it’s natural to read that the "text is trimmed with” the parameter set. The former is, “the text is trimming with” the parameter set.

-David

···

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


(Kevin Schlei) #8

(reply-all reposting, sorry I'm not very list-serve savvy)

I think it's only unclear because p is not a descriptive name (next and

current aren't terribly helpful either), and we don't have any context or
type information.

Put another way: it's up to variable names to clarify what a method does.
I'm not in favor of that, and right now it's not broken. (To be clear: I'm
all for properly naming variables. I hope everyone else is the same.)

True, I intentionally chose ambiguous variable names to illustrate a point.
However, I have to admit that when unpacking optionals I have caught myself
doing this occasionally:

if let p = proximity {

}

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.

In my experience, encountering new code is an exercise in unpacking
individual components in order to understand the whole. Making the
individual parts convey less makes the whole thing harder to absorb.

···

On Tue, Feb 2, 2016 at 2:48 PM, <swift@lng.la> wrote:

On Feb 2, 2016, at 11:16, Kevin Schlei via swift-evolution < > swift-evolution@swift.org> wrote:

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does.
In this case, it returns a new string instance. Where is that explained? In
the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What
does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all
the hints. But this line:

I think it's only unclear because p is not a descriptive name (next and
current aren't terribly helpful either), and we don't have any context or
type information.

let next = current.locationByUpdatingProximity(p)

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)

Ultimately, I don't think this is a very difficult pattern to learn. Maybe
the first handful of times you see it you'll need to read the documentation
to know exactly what it's doing, but once you've seen it a few times, it's
an instantly recognizable pattern. If you see a gerund method, it returns a
new thing by doing the verb to the thing. Is it worth the redundancy and
noise to save new developers from possibly needing to look at a method's
documentation a few times?

I see the tradeoff here as a minor, essentially one-time decrease in
clarity for new developers, and a small but indefinite increase in clarity
for everyone else.

When is the last time you saw a gerund (-ing) as a method name? I wouldn't
let my students write that. Gerunds make good boolean properties. How would
you even read the first line above out loud? Probably by filling in the
words in the second line, magically.

Not having used this pattern before isn't a valid reason to not start
using it, and the API design guidelines already provide a fine pattern for
boolean properties, so we don't need gerunds for them.

My second major issue is that autocomplete grouping is totally lost when
dropping the type returned at the beginning of the call. How many of us
learned a *ton* when we just autocompleted .stringBy? Look at all the
things you can do! But by removing the 'useless word' (really don't like
that flag name) we have no grouping of constructor methods.

I agree that this is kind of unfortunate, but I also don't think that it's
a good idea to limit our API design for the sake of autocomplete discovery.
Documentation is readily available and is a far better form of discovery
since you don't just see things that start with the same prefix that you're
using. The tradeoff is that you have to go out of your way to do it, but
these are the kinds of good habits we should be teaching students.

I see a lot of discussion on how to deal with 'with' and 'by' and other
words, but I want to strongly suggest that the current naming practices
provide context and clarity. It makes code readable and accessible. Don't
forget about when you didn't know how to code! These method names are
teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't
clarity be prioritized over brevity (where have I seen that...)

I can't put it better than another forums poster:

Does the Swift team seriously believe that systematically parsing and

extensively munging patterns in not-quite-natural-language is tractable to
support all the corner cases for? And that, even if it were, that it could
avoid confusion in less-than-perfect codebases? The idea that this will
somehow benefit a language, particularly one in which clear and obvious
bridging is so vital is *insane*. The best it can do is a reasonable
job, with some amount of either unfixable brokenness forced upon developers
in perpetuity, or constant churn stemming from perpetual fixing of
brokenness. Swift's translation is currently simple to reason about, and
the language as a whole has got a really great thing going on. I'm really
happy with where it is at this moment. Why ruin it by boneheadedly
detonating the utility of two years of progress in literature and the
library of online information about Swift? Seriously, why?

On Tue, Feb 2, 2016 at 1:04 PM, Kevin Schlei <kevinschlei@gmail.com> > wrote:

I am strongly against the proposed changes to the translation of
Objective-C APIs. I think the changes promote terseness for terseness sake,
lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Preston Sumner) #9

To me, it reads like documentation: “content” is assigned the list item view’s text, trimming whitespace and newlines.

Preston

···

On Feb 2, 2016, at 12:16 PM, Kevin Schlei via swift-evolution <swift-evolution@swift.org> wrote:

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does. In this case, it returns a new string instance. Where is that explained? In the documentation. Nowhere near the method call.


(marc hoffman) #10

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does. In this case, it returns a new string instance. Where is that explained? In the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all the hints. But this line:

I think it's only unclear because p is not a descriptive name (next and current aren't terribly helpful either), and we don't have any context or type information.

let next = current.locationByUpdatingProximity(p)

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:

i could not agree more. i find this proposed change terrible, and it kills one of the core things that make Cocoa APIs great.


(Jarod Long) #11

I think it's a failing of the learning process if you're working with an API in a way that autocomplete discoverability is valuable but you don't know how to check its documentation. If this is a real problem, we should find better ways to teach people how to find and use the documentation.

Jarod

···

On Feb 2, 2016, at 11:49, Aaron Crespo via swift-evolution <swift-evolution@swift.org> wrote:

I think Kevin and I come from the same place and largely agree. I feel like this is trading in of accessibility and discoverability for the sake of terseness. This might be aesthetically pleasing but gives up many positive side effects the more descriptive names provide.

Consider the time before you knew you could or how to "check the documentation". Or the time spent scanning unfamiliar or long forgotten code.


(Jarod Long) #12

(reply-all reposting, sorry I'm not very list-serve savvy)

I think it's only unclear because p is not a descriptive name (next and current aren't terribly helpful either), and we don't have any context or type information.

Put another way: it's up to variable names to clarify what a method does. I'm not in favor of that, and right now it's not broken. (To be clear: I'm all for properly naming variables. I hope everyone else is the same.)

True, I intentionally chose ambiguous variable names to illustrate a point. However, I have to admit that when unpacking optionals I have caught myself doing this occasionally:

if let p = proximity {

}

To be honest, I don't really agree with the practice of abbreviating names in that way unless it's something so common that it could be considered universally understood (like i in a loop, not that that's a very common pattern in Swift), so I wouldn't find myself in this kind of situation. But even then, unless the body of the if statement is enormous, you can easily refer to the binding to see that p stands for proximity, so context makes all the difference here.

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.

In my experience, encountering new code is an exercise in unpacking individual components in order to understand the whole. Making the individual parts convey less makes the whole thing harder to absorb.

I disagree -- when I'm looking at new code, I generally try to get a high-level understanding before diving into specifics, and extra verbosity tends to distract me from that and slow me down. Dense, terse code that leverages its context tends to be much quicker for me to understand since I don't have to filter out the noise words.

But it seems like this is something that's highly personal, and it may be that our disagreement simply comes from the fact that we read and process code differently. That's unfortunate if that's the case, since it would mean that one of us ultimately must accept that we're not working in an environment that's ideal for us individually, but at least we now have the opportunity to express our thoughts so we can make the best decision for the Swift community as a whole.

Jarod

···

On Feb 2, 2016, at 15:49, Kevin Schlei <kevinschlei@gmail.com> wrote:

On Tue, Feb 2, 2016 at 2:48 PM, <swift@lng.la <mailto:swift@lng.la>> wrote:

On Feb 2, 2016, at 11:16, Kevin Schlei via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does. In this case, it returns a new string instance. Where is that explained? In the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all the hints. But this line:

I think it's only unclear because p is not a descriptive name (next and current aren't terribly helpful either), and we don't have any context or type information.

let next = current.locationByUpdatingProximity(p)

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)

Ultimately, I don't think this is a very difficult pattern to learn. Maybe the first handful of times you see it you'll need to read the documentation to know exactly what it's doing, but once you've seen it a few times, it's an instantly recognizable pattern. If you see a gerund method, it returns a new thing by doing the verb to the thing. Is it worth the redundancy and noise to save new developers from possibly needing to look at a method's documentation a few times?

I see the tradeoff here as a minor, essentially one-time decrease in clarity for new developers, and a small but indefinite increase in clarity for everyone else.

When is the last time you saw a gerund (-ing) as a method name? I wouldn't let my students write that. Gerunds make good boolean properties. How would you even read the first line above out loud? Probably by filling in the words in the second line, magically.

Not having used this pattern before isn't a valid reason to not start using it, and the API design guidelines already provide a fine pattern for boolean properties, so we don't need gerunds for them.

My second major issue is that autocomplete grouping is totally lost when dropping the type returned at the beginning of the call. How many of us learned a *ton* when we just autocompleted .stringBy? Look at all the things you can do! But by removing the 'useless word' (really don't like that flag name) we have no grouping of constructor methods.

I agree that this is kind of unfortunate, but I also don't think that it's a good idea to limit our API design for the sake of autocomplete discovery. Documentation is readily available and is a far better form of discovery since you don't just see things that start with the same prefix that you're using. The tradeoff is that you have to go out of your way to do it, but these are the kinds of good habits we should be teaching students.

I see a lot of discussion on how to deal with 'with' and 'by' and other words, but I want to strongly suggest that the current naming practices provide context and clarity. It makes code readable and accessible. Don't forget about when you didn't know how to code! These method names are teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't clarity be prioritized over brevity (where have I seen that...)

I can't put it better than another forums poster:

Does the Swift team seriously believe that systematically parsing and extensively munging patterns in not-quite-natural-language is tractable to support all the corner cases for? And that, even if it were, that it could avoid confusion in less-than-perfect codebases? The idea that this will somehow benefit a language, particularly one in which clear and obvious bridging is so vital is insane. The best it can do is a reasonable job, with some amount of either unfixable brokenness forced upon developers in perpetuity, or constant churn stemming from perpetual fixing of brokenness. Swift's translation is currently simple to reason about, and the language as a whole has got a really great thing going on. I'm really happy with where it is at this moment. Why ruin it by boneheadedly detonating the utility of two years of progress in literature and the library of online information about Swift? Seriously, why?

On Tue, Feb 2, 2016 at 1:04 PM, Kevin Schlei <kevinschlei@gmail.com <mailto:kevinschlei@gmail.com>> wrote:
I am strongly against the proposed changes to the translation of Objective-C APIs. I think the changes promote terseness for terseness sake, lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #13

I think Kevin and I come from the same place and largely agree. I feel like
this is trading in of accessibility and discoverability for the sake of
terseness. This might be aesthetically pleasing but gives up many positive
side effects the more descriptive names provide.

This is not about aesthetics; it's about clarifying code by omitting
details that don't carry their weight in terms of communicative power.

Consider the time before you knew you could or how to "check the
documentation". Or the time spent scanning unfamiliar or long
forgotten code.

I am considering that. Code like this is hard for me to read because
there is a great deal of information that is either redundant or
irrelevant, and I have to filter it out.

  let cleansedString = listItemView.stringValue.stringByTrimmingCharactersInSet(
     NSCharacterSet.whitespaceAndNewlineCharacterSet())

The above is not an improvement over

  let cleansed = listItemView.stringValue.trimming(.whitespaceAndNewlines)

in understandability, especially when you put it in context in a large
program. Programmers have a great deal of complexity to manage, and
giving them twice the number of words to process in order to understand
a piece of code makes their job a lot harder.

We don't write English that way, for good reason: it results in
impenetrable text. You might be able to pick apart the details of a
sentence with great precision, but you'll never be able to grasp the
meaning of a paragraph. The same applies to programs.

These concerns might be eased if consideration was also being given to the
first parameter rule.

If you mean the default for first parameters, some of us are thinking
about that; just not in this thread please. But regardless, I don't see
how changing the default would address any of your concerns about
comprehensibility of code that follows the guidelines.

···

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

And the (now) odd difference between initializers and function
parameter names. Apply the same rules as any parameter name.

Stealing Kevins example:

let next = current.updating(proximity: p)

Not great but better.

On Tue, Feb 2, 2016 at 2:16 PM, Kevin Schlei via swift-evolution < > swift-evolution@swift.org> wrote:

Sorry for the premature send! Continuing:

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

For a beginning programmer, there is no indication of what .trimming does.
In this case, it returns a new string instance. Where is that explained? In
the documentation. Nowhere near the method call.

So are we reduced now to looking up documentation just to read code? What
does this line do:

let next = current.updating(p)

It's 100% unclear because you're relying on parameter names to contain all
the hints. But this line:

let next = current.locationByUpdatingProximity(p)

Lets you know that:

1. we're returning a *'location'*
2. '*by* *updating' *current with a new *'proximity'*

When is the last time you saw a gerund (-ing) as a method name? I wouldn't
let my students write that. Gerunds make good boolean properties. How would
you even read the first line above out loud? Probably by filling in the
words in the second line, magically.

My second major issue is that autocomplete grouping is totally lost when
dropping the type returned at the beginning of the call. How many of us
learned a *ton* when we just autocompleted .stringBy? Look at all the
things you can do! But by removing the 'useless word' (really don't like
that flag name) we have no grouping of constructor methods.

I see a lot of discussion on how to deal with 'with' and 'by' and other
words, but I want to strongly suggest that the current naming practices
provide context and clarity. It makes code readable and accessible. Don't
forget about when you didn't know how to code! These method names are
teaching tools!

Finally, I just want to ask: why? What is the great benefit? Shouldn't
clarity be prioritized over brevity (where have I seen that...)

I can't put it better than another forums poster:

Does the Swift team seriously believe that systematically parsing and

extensively munging patterns in not-quite-natural-language is tractable to
support all the corner cases for? And that, even if it were, that it could
avoid confusion in less-than-perfect codebases? The idea that this will
somehow benefit a language, particularly one in which clear and obvious
bridging is so vital is *insane*. The best it can do is a reasonable
job, with some amount of either unfixable brokenness forced upon developers
in perpetuity, or constant churn stemming from perpetual fixing of
brokenness. Swift's translation is currently simple to reason about, and
the language as a whole has got a really great thing going on. I'm really
happy with where it is at this moment. Why ruin it by boneheadedly
detonating the utility of two years of progress in literature and the
library of online information about Swift? Seriously, why?

On Tue, Feb 2, 2016 at 1:04 PM, Kevin Schlei >> <kevinschlei@gmail.com> >> wrote:

I am strongly against the proposed changes to the translation of
Objective-C APIs. I think the changes promote terseness for terseness sake,
lose vital context in method names, and are a huge loss pedagogically.

If you teach programming, you'll know why this line will be a nightmare:

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave


(Dave Abrahams) #14

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.

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.

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?

Ultimately, I don't think this is a very difficult pattern to
learn. Maybe the first handful of times you see it you'll need to
read the documentation to know exactly what it's doing, but once
you've seen it a few times, it's an instantly recognizable
pattern. If you see a gerund method, it returns a new thing by doing
the verb to the thing. Is it worth the redundancy and noise to save
new developers from possibly needing to look at a method's
documentation a few times?

I really do not like the -ing form; it reads backwards. I intuitively
expected the object of the “trimming” to be the parameters, not the
instance invoking the method.

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

Whereas when I read the above, it’s natural to read that the "text is
trimmed with” the parameter set. The former is, “the text is trimming
with” the parameter set.

This is why you're supposed to first try the "ed" form. The "ing" form
only comes into play (quoting the guidelines):

     When adding “ed” is not grammatical because the verb has a direct
     object

and in those cases, it reads forwards.

···

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:

--
-Dave


(Kevin Schlei) #15

It trims. In this case, it trims whitespace and newlines. I think
that's actually pretty clear.

I wouldn't explain what trimming: does to a new student by just saying 'it
trims', because by that explanation it sounds like it mutates its caller.
The clarity provided by the verbosity of the old method name will be missed.

I do appreciate your clarification of how my updating: example would not
meet the new standards, but I find all of the new standards difficult to
get right. If 'Proximity' is a type, wouldn't that be truncated because it
doesn't communicate semantics? It feels like half of the methods will have
clarifying qualifiers, and half won't. I think that will make the language
less consistent.

It is. You just have a different idea about what creates clarity in

source code. IMO, clarity is provided by communicating semantics, *not*
by repeating non-semantic details such as which specific types are in
use. By eliminating words that don't communicate semantics, you make
the semantics clearer. If we didn't believe in this approach, Swift
wouldn't have type inference.

You've solved the repetition of type detail be removing all type detail.
That line is clear to you because you already know that .
whitespaceAndNewlines is an NSCharacterSet, and that string trims
characters instead of something else, like length. There is nothing written
on that line of code that tells me what .whitespaceAndNewlines is. It looks
like a poorly capitalized enum.

We don't always read code from within our tools. I can't command-click
variables on Stackoverflow, WWDC slides, GitHub. I could read 100 lines of
trimming: and still not know that NSCharacterSet exists.

···

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


(David Owens II) #16

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.

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.

-David

···

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


(Dave Abrahams) #17

It trims. In this case, it trims whitespace and newlines. I think
that's actually pretty clear.

I wouldn't explain what trimming: does to a new student by just saying 'it
trims', because by that explanation it sounds like it mutates its
caller.

Uh, fine, for new students: it makes a copy, trims that, and returns it.

The clarity provided by the verbosity of the old method name will be missed.

I do appreciate your clarification of how my updating: example would not
meet the new standards, but I find all of the new standards difficult to
get right. If 'Proximity' is a type, wouldn't that be truncated because it
doesn't communicate semantics?

It would be omitted if it were a strong type. If it was just a
typealias for Float, you'd add it to clarify the role of the argument.

It feels like half of the methods will have clarifying qualifiers, and
half won't. I think that will make the language less consistent.

Yes, it is less uniform than code written to the existing conventions.
On balance, it leads to clearer code.

If this makes you work a little harder to choose good API names, that's
a net plus. In reviewing existing APIs written against the existing
standards, I can't tell you how many times I've found names that are
ambiguous—or worse, strongly imply something unintented—but fit the
usual linguistic patterns. As long as you spell it "noun1ByVerbingNoun2"
or "verbWithNoun" people who are used to reading this kind of
declaration but aren't paying *really close* attention to detail nod
their head and says "yep, sounds about right," and fail to even look at
the resulting code, much less read it the way a new maintainer will.
The familiar patterns lead us into complacency.

It is. You just have a different idea about what creates clarity in

source code. IMO, clarity is provided by communicating semantics, *not*
by repeating non-semantic details such as which specific types are in
use. By eliminating words that don't communicate semantics, you make
the semantics clearer. If we didn't believe in this approach, Swift
wouldn't have type inference.

You've solved the repetition of type detail be removing all type detail.
That line is clear to you because you already know that .
whitespaceAndNewlines is an NSCharacterSet, and that string trims
characters instead of something else, like length.

Not really. I do know is that "trim" is a term of art for string
manipulation, and I happen to know what it means. Even if you put the
type information back in, nothing in the name is going to tell you that
this call removes stuff on the ends of the string but not in the
middle. That's a much more essential piece of information than the type
of the argument.

There is nothing written on that line of code that tells me what
.whitespaceAndNewlines is. It looks like a poorly capitalized enum.

You can't read one line of code by itself anyway just like you can't
generally take a sentence out of context and understand it.

We don't always read code from within our tools. I can't command-click
variables on Stackoverflow, WWDC slides, GitHub. I could read 100 lines of
trimming: and still not know that NSCharacterSet exists.

Fortunately if someone wrote 100 lines of trimming with no other
context, it would be pretty easy to infer that by the end there would be
nothing left :wink:

P.S. FWIW, as a standard library developer, I mostly can't use Xcode for
     development, so command-click is not something I get to rely on.

···

on Wed Feb 03 2016, Kevin Schlei <kevinschlei-AT-gmail.com> wrote:

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

--
-Dave


#18

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?

Gwendal

···

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?


(Preston Sumner) #19

Where context fails, tools can go the rest of the way (option-clicking a symbol in Xcode displays a documentation popover). Failing that, referring to external documentation isn’t necessarily a failure of the API. No API can self-document everything. Cocoa methods already can’t be relied on for type documentation.

What are the types of s2, options, and result?
let result = s1.compare(s2, options: [])

Is copy a noun or a verb?
foo.copy()

What type is p?
string.hasPrefix(p)

What is foo?
obj.isDescendantOf(foo)

Preston

···

On Feb 3, 2016, at 8:46 AM, Kevin Schlei via swift-evolution <swift-evolution@swift.org> wrote:

On Tue, Feb 2, 2016 at 3:21 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
It trims. In this case, it trims whitespace and newlines. I think
that's actually pretty clear.

I wouldn't explain what trimming: does to a new student by just saying 'it trims', because by that explanation it sounds like it mutates its caller. The clarity provided by the verbosity of the old method name will be missed.

I do appreciate your clarification of how my updating: example would not meet the new standards, but I find all of the new standards difficult to get right. If 'Proximity' is a type, wouldn't that be truncated because it doesn't communicate semantics? It feels like half of the methods will have clarifying qualifiers, and half won't. I think that will make the language less consistent.

It is. You just have a different idea about what creates clarity in
source code. IMO, clarity is provided by communicating semantics, *not*
by repeating non-semantic details such as which specific types are in
use. By eliminating words that don't communicate semantics, you make
the semantics clearer. If we didn't believe in this approach, Swift
wouldn't have type inference.

You've solved the repetition of type detail be removing all type detail. That line is clear to you because you already know that .whitespaceAndNewlines is an NSCharacterSet, and that string trims characters instead of something else, like length. There is nothing written on that line of code that tells me what .whitespaceAndNewlines is. It looks like a poorly capitalized enum.

We don't always read code from within our tools. I can't command-click variables on Stackoverflow, WWDC slides, GitHub. I could read 100 lines of trimming: and still not know that NSCharacterSet exists.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jordan Rose) #20

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 '".)

Jordan

···

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.