[swift-evolution] Smart KeyPaths

Matthew Johnson matthew at anandabits.com
Fri Mar 17 19:44:56 CDT 2017


> On Mar 17, 2017, at 6:29 PM, Joe Groff <jgroff at apple.com> wrote:
> 
> 
>> On Mar 17, 2017, at 4:25 PM, Matthew Johnson <matthew at anandabits.com <mailto:matthew at anandabits.com>> wrote:
>> 
>> 
>> 
>> Sent from my iPhone
>> 
>> On Mar 17, 2017, at 6:09 PM, Joe Groff <jgroff at apple.com <mailto:jgroff at apple.com>> wrote:
>> 
>>> 
>>>> On Mar 17, 2017, at 4:05 PM, Matthew Johnson <matthew at anandabits.com <mailto:matthew at anandabits.com>> wrote:
>>>> 
>>>> 
>>>> 
>>>> Sent from my iPad
>>>> 
>>>> On Mar 17, 2017, at 5:38 PM, Joe Groff via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> 
>>>>> 
>>>>>> On Mar 17, 2017, at 12:34 PM, David Hart via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>>> 
>>>>>> Sent off-list by mistake:
>>>>>> 
>>>>>> Nice proposal. I have a few comments inline:
>>>>>> 
>>>>>>> On 17 Mar 2017, at 18:04, Michael LeHew via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>>>> 
>>>>>>> Hi friendly swift-evolution folks,
>>>>>>> 
>>>>>>> The Foundation and Swift team  would like for you to consider the following proposal:
>>>>>>> 
>>>>>>> Many thanks,
>>>>>>> -Michael
>>>>>>> 
>>>>>>> Smart KeyPaths: Better Key-Value Coding for Swift
>>>>>>> Proposal: SE-NNNN
>>>>>>> Authors: David Smith <https://github.com/Catfish-Man>, Michael LeHew <https://github.com/mlehew>, Joe Groff <https://github.com/jckarter>
>>>>>>> Review Manager: TBD
>>>>>>> Status: Awaiting Review
>>>>>>> Associated PRs:
>>>>>>> #644 <https://github.com/apple/swift-evolution/pull/644>
>>>>>>> Introduction
>>>>>>> We propose a family of concrete Key Path types that represent uninvoked references to properties that can be composed to form paths through many values and directly get/set their underlying values.
>>>>>>> 
>>>>>>> Motivation
>>>>>>> We Can Do Better than String
>>>>>>> 
>>>>>>> On Darwin platforms Swift's existing #keyPath() syntax provides a convenient way to safely refer to properties. Unfortunately, once validated, the expression becomes a String which has a number of important limitations:
>>>>>>> 
>>>>>>> Loss of type information (requiring awkward Any APIs)
>>>>>>> Unnecessarily slow to parse
>>>>>>> Only applicable to NSObjects
>>>>>>> Limited to Darwin platforms
>>>>>>> Use/Mention Distinctions
>>>>>>> 
>>>>>>> While methods can be referred to without invoking them (let x = foo.bar instead of  let x = foo.bar()), this is not currently possible for properties and subscripts.
>>>>>>> 
>>>>>>> Making indirect references to a properties' concrete types also lets us expose metadata about the property, and in the future additional behaviors.
>>>>>>> 
>>>>>> What metadata is attached? How is it accessed? What future features are you thinking about?
>>>>> 
>>>>> To begin with, you'd have limited ability to stringify a key path. Eventually we'd like to support other reflectiony things, including:
>>>>> 
>>>>> - Asking for the primary key paths a type supports
>>>>> - Asking for a key by name or index
>>>>> - Breaking a key path down by components
>>>>> 
>>>>> I also see key path objects as a good way of eventually addressing some of the design problems we ran up against with property behaviors (https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md <https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md> from last year), including the problem of what exactly a property behavior declaration *is* (a type? a protocol? a function-like thing? something completely new?), and the problem of handling "out-of-band" operations on a property beyond getting and setting, such as clearing a cached lazy value, registering for notifications on an observable property, and so on. I think it would be natural to express property behaviors as a user-defined key path type; the key path type can provide the get/set logic for the property as well as any other interesting operations the property supports. This answers the questions of both what behaviors look like (they're just types that conform to KeyPath) and how they extend properties with new actions (they're just methods of the key path value) fairly nicely.
>>>> 
>>>> Very interesting!  This sounds like it would enable a very nice design in a project I'm working on right now.  I'm looking forward to seeing this take shape in the future.
>>>> 
>>>> It sounds like it wouldn't solve one use case I was hoping property behaviors might solve though.  Sometimes we have a property that we would like to make a constant but cont because we can't set it until phase 2.  I would really like to have some notion of a "phase 2 initialized constant" which would provide a much stronger guarantee than IUO does.  There would be a very small window where a trap is possible between phase 1 and when it is set in phase 2.  It would probably make more sense to actually think of this as phase 1.5 where all of these properties must be initialized to a non-nil value, but self can be used in the initializing expressions.
>>> 
>>> I think that kind of use case can be handled even by the previous property behaviors proposal, by having a behavior that presents a non-optional property that only allows initialization by being set once, and traps if gotten before being initialized.
>> 
>> Didn't it require trapping if set more than once?  And it didn't offer a way to require initialization during phase 2 did it?
> 
> Yes, but perfectly closing those holes requires a much more complex type system than we have. Perfect is the enemy of good, and I think trapping on misuse gets you the lion's share of the benefit, and would still be a massive improvement over IUO.

Yes, I agree that it would be a massive improvement.  I just wish there was a way to solve this that didn’t require fancy type system stuff.  We already have relatively complex initialization rules that exist outside the type system that track initialization.  It would be nice if we could solve this using a small enhancement to those rules.  For example, we could have some kind of attribute or access control that is only available for IUO properties that restricts the setter to only be available in the initializer and guarantees that it is set to non-nil on exit of init.  Maybe it’s too much of a special case to do this, but it would be really cool to have this hole plugged.

> 
> -Joe

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


More information about the swift-evolution mailing list