[swift-evolution] [Review #2] SE-0161: Smart KeyPaths: Better Key-Value Coding for Swift

Karl Wagner razielim at gmail.com
Mon Apr 10 04:22:37 CDT 2017

> On 9 Apr 2017, at 19:36, Tino Heth via swift-evolution <swift-evolution at swift.org> wrote:
> -1:
> Although prefix "\" is imho the nicest variation that has been officially suggested for this feature (I still like infix ":" better; maybe I've been using classic MacOS to long), there is no general agreement, and many people that voted "+1" did so despite preferring a different syntax, just because they want to have the feature asap.
> But haste is a bad counsellor, and if we learned anything from the disaster of "new private", we shouldn't rush and constitute how an obviously important (or at least popular) feature should look like without taking into account the big picture:
> KeyPaths are at least entwined with method references and reflection, so until we have a concrete idea of those ties, no narrow proposal should be implemented*.
> - Tino
> * preliminary acceptance with delayed implementation would be fine for me — I just don't want to paint ourselves into a corner...
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Or the other way around - if its implementable right now, we should do it and gather feedback on the syntax in real usage. I think we’re all agreed on the functionality.

Personally, I’d like to see these smart KeyPaths become more of a first-class language feature. We should define a new family of operators to use with them, instead of named methods. The “::” member reference operator (on a type, returning a keypath, or on a keypath, returning a sub-keypath) could be one.

Subscripting: replace with arrow (indirect access) operator. Parallels the dot operator for direct access. “Indirect” here means the keypath, since it may be invalid for this object and return nil (depending on which keypath you provide).

let name = luke->firstFriendNameKeyPath // “Han Solo"
let name = luke->friends[0]::name // Equivalent to luke.friends[0].name

Appending: replace with backslash operator.

let personName = Person::name
let nameToFind = luke->personName // “Luke Skywalker”
for p in people {
   if p->friends[0]\personName == nameToFind { return p }

If you are directly entering a keypath, we could infer the type for the :: operator, so you could just directly type members in. That’s fine - if you’re accessing a known member on a known type, even by keypath, “->" will get optimised in to a direct access anyway.

let name = AnyKeyPath(Person::name)
for p in people {
    if let n = p->friends[0]\name, n == nameToFind { return p }

- Karl

More information about the swift-evolution mailing list