[swift-evolution] Smart KeyPaths

Matthew Johnson matthew at anandabits.com
Wed Mar 29 20:49:46 CDT 2017


> On Mar 29, 2017, at 8:45 PM, Douglas Gregor via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> 
> Sent from my iPhone
> 
> On Mar 29, 2017, at 4:52 PM, Brent Royal-Gordon <brent at architechies.com <mailto:brent at architechies.com>> wrote:
> 
>>> On Mar 29, 2017, at 4:13 PM, Michael J LeHew Jr via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> Thanks for the feedback everyone!  We have pushed a changed a bit ago to the proposal reflecting these desires.
>>> 
>>> https://github.com/apple/swift-evolution/pull/644/files <https://github.com/apple/swift-evolution/pull/644/files>
>> Quoting from the proposal:
>> 
>>> luke[keyPath: #keyPath(.friends[0].name)]
>> 
>> Really? I can understand marking one or the other, but both, even when there's no ambiguity?
>> 
>> Let's pretend we're the type checker here. The `luke[keyPath: _]` part will create a context where we know we have an `AnyKeyPath`, `PartialKeyPath<Person>`, `KeyPath<Person, U>`, or `WritableKeyPath<Person, U>`. So if the core team's concern is about namespace clashes between `Person`'s static members and key paths, why not hang the key paths off the various `KeyPath` types? That is, this:
>> 
>> 	struct Person {
>> 		var friends: [Person]
>> 		var name: String
>> 	}
>> 
>> Implies this:
>> 
>> 	extension PartialKeyPath where Root == Person {
>> 		static let friends: WritableKeyPath<Person, [Person]>
>> 		static let name: WritableKeyPath<Person, String>
>> 	}
>> 
>> And this:
>> 
>> 	#keyPath(Person, .friends[0].name)
>> 
>> Desugars to this:
>> 
>> 	PartialKeyPath<Person>.friends[0].name
>> 
>> So in a context where you already know you're passing a key path, you can simply write this:
>> 
>> 	luke[keyPath: .friends[0].name]
>> 
>> Which applies normal "unresolved member" logic to look it up in `PartialKeyPath`.
> 
> Yes, this can be done via "unresolved member lookup". It's a little different---unresolved member lookup usually can't handle chaining---but the type checker could support it. 
> 
>> 
>> The result would be that you would have to explicitly, syntactically mark key paths except when the context already implied you were looking for one. In an unconstrained generic context, you would not get a key path without using `#keyPath` or explicitly naming a key path type. You would only need to worry about clashes if a call was overloaded to accept *both* `T` and `PartialKeyPath<T>`; if we found that possibility troubling, we could penalize unresolved member lookups that resolve to key paths, so type inference would favor static members over key paths even in those cases.
>> 
>> Would that work for people? 
> 
> It's technically feasible. It makes ".foo" more contextually sensitive, which is probably fine. 

It would work nicely for the use cases I have.

> 
>   - Doug
> 
>> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


More information about the swift-evolution mailing list