API Guidelines: dropFirst?


(Patrick Pijnappel) #1

What is the rationale behind the name dropFirst()? Being a non-mutating
method it should clearly be e.g. droppingFirst() according to the API
Naming Guidelines.

I can't seem to find the SE thread dealing with this.


(Brent Royal-Gordon) #2

What is the rationale behind the name dropFirst()? Being a non-mutating method it should clearly be e.g. droppingFirst() according to the API Naming Guidelines.

Like many `Sequence` and `Collection` operations, `dropFirst()` is a result of the "term of art" exception, which is implied by the "Use Terminology Well" section of the API Guidelines: <https://swift.org/documentation/api-design-guidelines/#use-terminology-well>

Many languages use `dropWhatever` or `drop_whatever` for operations which return some sort of list with some of its leading or trailing elements removed. For instance:

* Ruby (which I happen to have in Dash) has `drop(n)` and `drop_while` methods.
* Haskell has `drop n`, `dropWhile`, and `dropWhileEnd` functions.
* Scala has a `drop(n)` method.
* R has a `dropFirst` function.

The standard library has chosen to break its usual patterns in order to maintain consistency with languages like these.

Personally, I believe the term of art exception has been misapplied in this area of the language; the precedents are not very strong, and the resulting APIs form a patchwork of inconsistent names rather than a coherent family. The term of art exception increases the clarity of calls like `map` and `filter` where the names are truly universal, but it impedes the clarity of the whole family of `first`/`prefix`/`suffix`/`last` calls, and the names should be revisited and rationalized. But that hasn't happened yet.

···

--
Brent Royal-Gordon
Architechies


(Dave Abrahams) #3

I agree that we need to revisit this area. Even filter can potentially
be improved upon. The polarity of its closure is far from obvious even
if you know the terms of art.

···

on Thu Jun 16 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

What is the rationale behind the name dropFirst()? Being a

non-mutating method it should clearly be e.g. droppingFirst()
according to the API Naming Guidelines.

Like many `Sequence` and `Collection` operations, `dropFirst()` is a
result of the "term of art" exception, which is implied by the "Use
Terminology Well" section of the API Guidelines:
<https://swift.org/documentation/api-design-guidelines/#use-terminology-well>

Many languages use `dropWhatever` or `drop_whatever` for operations
which return some sort of list with some of its leading or trailing
elements removed. For instance:

* Ruby (which I happen to have in Dash) has `drop(n)` and `drop_while` methods.
* Haskell has `drop n`, `dropWhile`, and `dropWhileEnd` functions.
* Scala has a `drop(n)` method.
* R has a `dropFirst` function.

The standard library has chosen to break its usual patterns in order to maintain consistency with languages like these.

Personally, I believe the term of art exception has been misapplied in
this area of the language; the precedents are not very strong, and the
resulting APIs form a patchwork of inconsistent names rather than a
coherent family. The term of art exception increases the clarity of
calls like `map` and `filter` where the names are truly universal, but
it impedes the clarity of the whole family of
`first`/`prefix`/`suffix`/`last` calls, and the names should be
revisited and rationalized. But that hasn't happened yet.

--
-Dave


(Haravikk) #4

I’m not a big fan of the term of art exception personally.

That said I actually think it’s useful to have these methods slightly different as if I understand them correctly they’re not strictly non-mutating; a Sequence doesn’t guarantee that it can be consumed over and over without changing, as it could represent a buffer or some other construct that’s consumed as it’s accessed, so calling dropFirst() on a sequence, then calling it again on the same sequence may not yield the same result both times, for that you want a Collection (or a specific sequence implementation with well defined behaviour), but for a generic sequence I don’t think you can trust the method to be non-mutating unless you know what the sequence is backed by, so it shouldn’t follow the rule for non-mutating methods.

Of course this gets us into a weird position when it comes to naming things consistently, because it means the name follows the mutating naming convention because it *could* be mutating behind the scenes. It’s one of those areas where things get confusing, as because a type is a struct, doesn’t mean it doesn’t use a share class instance behind the scenes for example, fun stuff :wink:

···

On 16 Jun 2016, at 08:39, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

What is the rationale behind the name dropFirst()? Being a non-mutating method it should clearly be e.g. droppingFirst() according to the API Naming Guidelines.

Like many `Sequence` and `Collection` operations, `dropFirst()` is a result of the "term of art" exception, which is implied by the "Use Terminology Well" section of the API Guidelines: <https://swift.org/documentation/api-design-guidelines/#use-terminology-well>

Many languages use `dropWhatever` or `drop_whatever` for operations which return some sort of list with some of its leading or trailing elements removed. For instance:

* Ruby (which I happen to have in Dash) has `drop(n)` and `drop_while` methods.
* Haskell has `drop n`, `dropWhile`, and `dropWhileEnd` functions.
* Scala has a `drop(n)` method.
* R has a `dropFirst` function.

The standard library has chosen to break its usual patterns in order to maintain consistency with languages like these.

Personally, I believe the term of art exception has been misapplied in this area of the language; the precedents are not very strong, and the resulting APIs form a patchwork of inconsistent names rather than a coherent family. The term of art exception increases the clarity of calls like `map` and `filter` where the names are truly universal, but it impedes the clarity of the whole family of `first`/`prefix`/`suffix`/`last` calls, and the names should be revisited and rationalized. But that hasn't happened yet.


(Vladimir) #5

Agree with your opinion. As I understand, these languages are functional languages or languages that have non-mutating methods as 1st class citizens. That is why 'dropX' in them by default means non-mutating method. They just don't need to somehow highlight that the method is non-mutating (but can highlight mutatuing method as in Ruby with '!').

In Swift prior 3.0 we had the same situation : there was 'default' non-mutating method and 'xxInPlace' for mutating method. Now, in Swift 3 we have "default" name for mutating methods and changed(to highlight) names for non-mutating. I believe there is no sense to leave methods other than (map/filter/reduce) in their initial view as this IMO will only confuse Swift coders that will expect 'droppingXXX' for non-mutating method.

IMO To keep the consistency with modern languages, we should have non-mutating methods with "default" name and "modified" for mutating.
As this solution was not chosen, then IMO we need to keep just map/filer/reduce for non-mutating as "term of art" and explicitly highlight that in documentation but use accepted naming rules for *all* other method names to reduce the confusion. Only in this way we'll have consistency and clear rules for naming. Otherwise we'll have a situation with naming in Swift 3.0 worse than in Swift 2.

And, if I don't need know/use these languages, why should I care of their naming elsewhere and have non-consistent names for some Swift methods?!

Btw, can't we say that 'sort' is also a term of art?

···

On 16.06.2016 10:39, Brent Royal-Gordon via swift-evolution wrote:

What is the rationale behind the name dropFirst()? Being a
non-mutating method it should clearly be e.g. droppingFirst()
according to the API Naming Guidelines.

Like many `Sequence` and `Collection` operations, `dropFirst()` is a
result of the "term of art" exception, which is implied by the "Use
Terminology Well" section of the API Guidelines:
<https://swift.org/documentation/api-design-guidelines/#use-terminology-well>

Many languages use `dropWhatever` or `drop_whatever` for operations
which return some sort of list with some of its leading or trailing
elements removed. For instance:

* Ruby (which I happen to have in Dash) has `drop(n)` and `drop_while`
methods. * Haskell has `drop n`, `dropWhile`, and `dropWhileEnd`
functions. * Scala has a `drop(n)` method. * R has a `dropFirst`
function.

The standard library has chosen to break its usual patterns in order to
maintain consistency with languages like these.

Personally, I believe the term of art exception has been misapplied in
this area of the language; the precedents are not very strong, and the
resulting APIs form a patchwork of inconsistent names rather than a
coherent family. The term of art exception increases the clarity of
calls like `map` and `filter` where the names are truly universal, but
it impedes the clarity of the whole family of
`first`/`prefix`/`suffix`/`last` calls, and the names should be
revisited and rationalized. But that hasn't happened yet.


(Brent Royal-Gordon) #6

That said I actually think it’s useful to have these methods slightly different as if I understand them correctly they’re not strictly non-mutating; a Sequence doesn’t guarantee that it can be consumed over and over without changing, as it could represent a buffer or some other construct that’s consumed as it’s accessed, so calling dropFirst() on a sequence, then calling it again on the same sequence may not yield the same result both times, for that you want a Collection (or a specific sequence implementation with well defined behaviour), but for a generic sequence I don’t think you can trust the method to be non-mutating unless you know what the sequence is backed by, so it shouldn’t follow the rule for non-mutating methods.

`dropFirst()`, like all `Sequence` APIs, works perfectly and reliably as long as you only access the contents of the `Sequence` once. Attempting to iterate the `Sequence` more than once may or may not work, so you shouldn't do it without static knowledge of the concrete type's behavior (for instance, knowledge that it's actually a `Collection`).

···

--
Brent Royal-Gordon
Architechies