[swift-evolution] [Returned for revision] SE-0161: Smart KeyPaths: Better Key-Value Coding for Swift

Douglas Gregor dgregor at apple.com
Wed Apr 5 18:01:28 CDT 2017

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md <https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md>

Hello Swift community,

The review of SE-0161 “Smart KeyPaths: Better Key-Value Coding for Swift” ran from March 30...April 5, 2017. The proposal was very well-received *except* that reviewers felt that the #keyPath syntax was far too heavy for this new language construct, and preferred the lighter-weight syntax of the pre-review drafts. This proposal is returned for revision to address the syntax.

The heavyweight #keyPath syntax was requested by the core team after reviewing earlier drafts, which used a far lighter syntax:

	// (Rejected) syntax from pre-review drafts
	let firstFriendsNameKeyPath = Person.friends[0].name
	print(luke[keyPath: .friends[0].name])

The core team’s specific concern was that these key path expressions (e.g., Person.friends[0].name) don’t make it sufficiently clear that the actual property accesses are being delayed, and that the contextual cues (“Person." vs. “luke.”) are insufficient to disambiguate for the human reader. Hence, the request for a different (more explicit) syntax.

Reviewers rightly point out that it is natural for key-paths to use the same syntax as unapplied instance method references, e.g., Person.someInstanceMethod produces a value of some function type with the “Self” type curried, e.g., (Person) -> (param-types) -> result-type. The core team agrees with this sentiment. The core team also felt that Swift’s existing unapplied method references suffer from the same clarity problems as the initial key-path syntax, i.e., that it isn’t sufficiently clear that the actual application of “self” is being delayed.

The core team has a specific proposal: use the backslash (‘\’) to as a leading indicator for key paths. Specifically,

	// Proposed syntax for second revision
	let firstFriendsNameKeyPath = \Person.friends[0].name
	print(luke[keyPath: \.friends[0].name])

The backslash is a visual cue that the actual application of this chain of property references is delayed, eliminating ambiguities, yet is still quite lightweight and feels “first-class” in the language.

The core team felt that, in the future, the backslash should also be used for unapplied instance method references, to match the proposed syntax for key paths and improve clarity for this non obvious feature. This change could be staged in as a revision to the accepted-but-never-implemented SE-0042: Flattening the function type of unapplied method references <https://github.com/apple/swift-evolution/blob/master/proposals/0042-flatten-method-types.md>, e.g.,

	// Proposed future syntax for unapplied instance method references
        class Person {
	  func instanceMethod(_: String) -> Int { … }

	let f1 = Person.instanceMethod   // to-be-deprecated; produces a value of type (Person) -> (String) -> Int
	let f2 = \Person.instanceMethod  // to-be-introduced via a revised SE-0042: produces a value of type (Person, String) -> Int

Such an approach gives us a way to stage in SE-0042 and get to eventual consistency between key paths and unapplied instance method references.

	- Doug
	Review Manager

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170405/b3a0ca80/attachment.html>

More information about the swift-evolution mailing list