Just got a notification from @Karoy_Lorentey in this PR that it's no longer recommended to add an extra space for conformances / inheritance / type constraints in stdlib.
struct Type<T : Protocol> { ... }
^
So it makes me wonder why this has changed!? (Personally I liked this style rule.)
We don’t have a rigid, machine-enforced formatting policy* for the stdlib, so its coding style is not set in stone — it slowly evolves to follow the changing preferences of all the fickle individuals working on it.
Coding style is mostly a matter of taste, so while it’s fun to argue about it, it is usually not very productive. It is also human nature to consider whatever arbitrary style one’s currently using as the self-evidently optimal choice.
Keeping all that firmly in mind, I believe it is obvious that having no space before the colon is the only correct option. If you forced me to rationalize it, I could come up with arguments like these:
Apple’s official developer documentation (books, guides, API docs, WWDC material) do not insert a space before the colon. The code samples in these documents define the closest thing we have for an official Swift coding style. Most third-party documentation and many, many projects follow it. I expect this is the style what most people see when they first learn Swift, so major deviations from it tend to stick out.
The most prominent feature of the stdlib’s own house style is the strict 80-character line length limit. This is amazingly useful in practice, but it is also a great stress test for edge cases in our line breaking conventions. With such a tight line limit, any non-essential horizontal whitespace feels wasteful. That extra space before the colon used to sometimes force a line break — causing such terrible, terrible anguish; an almost physical pain!
The extra space opens a huge gap in the middle of constraint clauses that visually cuts the declaration in half at a weird point.
It seems typographically inconsistent to add an extra space before the colon in struct Foo<Element : Hashable>, but not in let foo: Foo or foo.index(forKey: 42) or [“foo”: 42, “bar”: 13]. (There are clear differences in meaning, but it seems just as easy to recognize the various contexts without arbitrarily distinguishing some of them with leading spaces.)
<Some even more infuriating nonsense about how the colon is aesthetically designed to be followed by a space, but not preceded by one.>
Then again, I still sometimes catch myself typing the extra space, and it looks okay. We did not go and update existing code unless we had to modify it anyway - so the stdlib still uses the original spacing in lots of places. It’s fine.
* I think it would be valuable to define a single official Swift coding style, for use as a sort of normal form for Swift programs. I really like the stdlib style, but it’s probably too idiosyncratic to serve as such — we need something that feels a bit more familiar to most Swift programmers.
I get we're trying to be non-confrontational about style here, but your arguments are absolutely valid, not nonsense, and in line with how the colon is used in english language and the semantics it communicates there and in Swift.
It's not the most crucial issue, but let's not pretend there is no default answer for some questions ;)
Eh, there are lots of things in programming where we don't follow the rules for prose:
Trailing commas are allowed in array literals in Swift.
Inheritance colons conventionally have a space before them in both Objective-C and C++. Selector colons conventionally have no spaces on either side in Objective-C.
I don't even know how to map the "infix" "dot-as-member-access" to the "postfix" "dot-as-end-of-sentence", or even to the decimal point / radix point or thousands separator.
So I think as far as future discussions go, it's just one bullet point, not necessarily the default.
Sure, there are exceptions to every tendency. I think it's certainly a good heuristic to make programming languages read like natural language, so in a case of seeming confusion, it's a good idea to go back to what something means in the domain from which it is borrowed. Alright, that's maybe not the straight up "default"