I'd like to propose a Swift feature that promotes key paths to getter functions wherever appropriate.
It's common to write one-off closures that merely traverse from a root type into a value. For example, take the following User
struct:
struct User {
let email: String
let isAdmin: Bool
}
Given an array of users, we can use map
to gather an array of their emails.
users.map { $0.email }
We can also filter our array of users on isAdmin
to gather an array of admins.
users.filter { $0.isAdmin }
These ad hoc closures are short and sweet, but Swift already generates this code in the form of key paths.
The forum has previously proposed adding map
and flatMap
overloads that accept key paths as input. Popular libraries have added key path overloads, as well.
Adding an overload per function is a losing battle, though. It would be preferable to have first-class support from the language.
Swift should allow key paths of the form KeyPath<Root, Value>
wherever functions of the form (Root) -> Value
are allowed.
Our earlier examples end up becoming a little bit shorter.
users.map(\.email)
users.filter(\.isAdmin)
This feature would fall in the footsteps of Ruby, which allows Symbol#to_proc
to do a similar traversal.
users.map(&:email)
users.filter(&:isAdmin)
If we do not want compiler magic doing the automatic promotion, we could introduce a prefix operator, ^
for example, to the Standard Library. We can define it today:
prefix operator ^
prefix func ^ <Root, Value>(keyPath: KeyPath<Root, Value>) -> (Root) -> Value {
return { root in root[keyPath: keyPath] }
}
Ideally the compiler handles this for us, though!