Allow argument labels to be trailing or preceding

In my opinion, this idea is a non-starter because labels currently serve as a visual cue that an argument is to follow, and suddenly allowing them to be reordered would be a confusing fundamental change.

I think the examples given can be rewritten to match the expectations laid out by the current guidelines. For example:

insert(element: Element atSelection)

might be written along the lines of

updateSelectionPoint(with element: Element)

I'm just curious if others have wanted to be able to do something like this, since I've come across that desire several times before. Do you have some examples where you believe readability is hindered? (As a side note, in my mind this feature would be used with the alternative is less readable, though I take the point that syntactic sugar for its own sake increases the surface and will lead to bloat if not considered carefully).

Really, it's the colon : that serves as the visual cue, since labels are just identifiers. Also, commas will continue to serve as the visual cue that they already do when the argument label is absent.

Without commenting on other languages (since I don't speak any that don't use SVO), that doesn't appear to be a faithful renaming of the method. It updates, not inserts. Regardless, I guess I just don't believe that there is a rule to reorder the labels which will always result in a more readable method. IMO even update(_ element: Element atSelection) is clearer than the alternative you propose.

Without getting lost in the weeds here, there are a variety of ways to name such a method: insertAtSelectionPoint(with:) or even making the insertion point implicit ala NSText.

Another consideration is Objective-C compatibility.

Swift is already a multi-paradigm language which allow a user to express a multitude of ideas and patterns in various wildly different ways. But I feel that most of these are necessary and well-justified.

However, this adds complexity to the language, not to be able to express new ideas, solve new problems, write more concise code, increase correctness or expressitivity. It’s for the purpose of making functions feel more natural to a speaker of some other language. To allow for many different syntaxes within a single code base, will be like reading a book written in many languages.

Organizations, businesses and open source projects will have to resolve to strict linting rules to enforce a certain style within the project. And even if some organization go for e.g German style and German identifier names, they still have to deal with the English protocol names, standard classes, function names and labels in stdlib and Foundation.

Dialects will evolve, and going from one code base to another will require the user to switch mental models.

All for what? What new problems will it help solve?

The problem as I see it isn't that naming this kind of method is impossible, it's that there's no way to phrase it that aligns with Swift's API design guideline of forming grammatical English phrases. "Insert at selection point with element" gets the point across, but it isn't a phrasing that would be used outside of our current constraints. More importantly, it's inconsistent with the APIs that /can/ follow the guideline, potentially hurting discoverability and making the relationships between those sets of methods less clear.

As a meta point, I wish we as a community would try to avoid this type of strong language in these discussions. I feel like it's becoming more common lately, and I think it sets an unwelcoming tone and can shut down conversations prematurely.

2 Likes

Thanks for expressing that thought better than I was able to. Obviously we can write descriptive method names today, but my original point was that if all labels come before the arguments they label, we are forced into contorting our "sentences" in strange ways that may not even be grammatical.

Even if we set aside the discussion of other languages, it will allow for expressing some method calls more clearly and readably, since they will read as grammatical English sentences. I'd like to know if you have examples which follow the API Design Guidelines but make Swift code less readable. I feel that the readability gains from writing

insert(element atSelection)

instead of

insertAtSelectionPoint(with: element)

are significant, and even more so if we have syntax highlighting improvements that distinguish argument labels from argument expressions.

2 Likes

The goal of the naming guidelines isn't to demand fluent English but to specify a set of reliable conventions for programmers and tool authors. Arbitrary reversal of arguments and labels would be very confusing. For example, insert(element atSelection) resembles insert(element: atSelection). And how would it translate to Objective-C? It's simpler to follow the current guidelines, which may not always lead to the most fluent English, but that's okay if the method name is clear enough to express the point.

3 Likes

And both of them are similar to insert(element, atSelection), which is also a valid method call in Swift today. But insert(element:) doesn't follow the guidelines, nor do I believe there are many variable identifiers beginning with prepositions (if they follow the guidelines). They are likely to be Bools (with names like isAtSelection) or enum cases (.atSelection).

Re: Objective-C, it's quite precedented to disallow the usage of certain language features if the associated Swift construct is @objc. Maybe the solution here is to require an Objective-C name to be provided if the function uses postfix labels so that you would have to write @objc(insertElementAtSelection:) in order to expose it.

There may be methods like insertAtSelectionPoint(with:) that aren't as fluent as common English equivalents like "insert element at selection point," but that's fine if it gets the point across. Note that this is just an example. A better API for this case would be to pass a selectionIndex argument to an insert(_:at:) method.

That's not an equivalent API -- the purpose of the method in this example is to free the caller from needing to deal with a selection index at all by managing it internally to the method. In that case, there is simply nothing to pass in as an at argument. I think fair to say that this type of API is reasonable and that there's not always going to be a way to contrive an extra argument to get the desired phrasing.

1 Like