I want to say some words against. In my mind, this feature needs more thoughts.
-
Compare theese 2 examples:
users.map { $0.email }
users.filter { $0.isAdmin }
vs
users.map(.email)
users.filter(.isAdmin)
The second variant is 4 symbols shorter. But, in my opinion, first variant is much more readable because of surrounding spaces and $0 argument.
The second variant is not intuitive and natural. For example, according to current swift grammar this expression can possibly be understood such way, that map closure returns an array of keypathes: Array<KeyPath<User, String>>. We must keep in mind some rules to understand it correctly. In fact, we see keypath in the code, but we must translate it into another mental construction inside our brain.
So, we are going to second paragraph.
-
It is said in proposal that this code is not allowed:
let kp = \User.email // KeyPath<User, String>
users.map(kp)
But this one is:
let f1: (User) -> String = \User.email
users.map(f1)
So, expression:
users.filter(.isAdmin)
means the following:
users.filter(.isAdmin as (User) -> Bool)
In fact, it is even more complex, because expression:
.isAdmin as (User) -> Bool
in fact means something like:
let closure: (User) -> Bool = { user in
return user[keyPath: .isAdmin]
}
Such rule is rather hard for understanding, especially for new users. We see a keypath (object), but should understand it as closure (function). It looks like some kind of compiler magic.
-
compactMap(.self) even 1 symbol longer than compactMap { $0 }.
-
We will see 3 constructions that make the same:
users.map({ $0.email })
users.map { $0.email }
users.map(.email)
First two are very similar semantically.
The first one is needed in if-let construction, because we can not omit parentheses:
if let user = users.map({ $0.email }) {
...
}
The second variant is used in other cases as syntactically more clear variant.
But after introducing the third variant, which one will be preferred by default?
In what cases one is more preferred than another?
Is it a good idea to combine them inside a scope?
Can we write adequate rule for linter to keep our code in tonus?
This proposal will add one more way to do well known things, but in more obvious way.
Every developer will have several variants of writing filter, map, etc. Different ways of writing the same things may confuse, will add noise to code and decrease its readability.
**Summary**:
In motivation paragraph of this proposal it is only said about more "shorter and sweeter syntax". But the price is:
- Increase complexity of language rules.
- Decreased readability, more noise / confusion. (it would be great to get comprehensible answers for questions from paragraph 4 in this message)
It seems that clarity/brevity balance will be worse after implementing this feature. Current syntax is compact enough, clear and unambiguous.
If there are no other arguable reasons except «shorter and sweeter syntax», this feature looks ambiguous, because the price is too high for such a little advantage.