[swift-evolution] Smart KeyPaths

Vladimir.S svabox at gmail.com
Thu Mar 30 09:14:29 CDT 2017


On 30.03.2017 16:12, Matthew Johnson via swift-evolution wrote:
>
>
> Sent from my iPad
>
> On Mar 30, 2017, at 12:35 AM, David Hart via swift-evolution
> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>
>>
>>
>>
>>
>> Sent from my iPhone
>> On 30 Mar 2017, at 01:13, 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
>>>
>>> -Michael
>>
>> I'm not a fan of the new syntax for creating key paths. To me, it feels
>> like they've been demoted to second class citizens of the language simply
>> because of how more verbose it now is. The new syntax is also too
>> confusingly similar to string key paths: I had to look closely at the
>> code to see the difference. Is there no symbol we can use to make it
>> ambiguous? Ideas:
>>
>> Person::friend.lastName
>> Person/friend.lastName
>> Person#friend.lastName
>>
>> I'm a fan of the first one as it has similarities to names pacing in C++.
>
> I'm a big fan of the last one.  I argued for it earlier as the best syntax
> to use if we deviated from the initial proposal.  I like it for several
> reasons:
>
> - # suggests compiler magic is at work which is the case here.
> - #friend.lastName works nicely as a shorthand in contexts expecting a key
> path with a fixed Root
> - # would work for unbound methods solving the no arguments case.  IMO all
> unbound members should be accessed using the same syntax.

Strong support. IMO proposal should be currently updated to unify the 
syntax of unbound methods access and key path access, IMO *this* should be 
one of the main targets of the proposal. I.e.

var method1 = MyType#foo() // unbound method
var method2 = MyType#foo(param:) // unbound method
var keypath = MyType#person.name // keypath

Personally I think the '@' could be used also as("type AT path"):

var method = MyType at foo() // unbound method
var keypath = MyType at person.name // keypath

But I agree that '#' is a strong marker that we are dealing with some 
compiler magic here.

> - # enables the possibility of mixing property access and method calls in
> the path as a future enhancement
>
> The arguments supporting this approach are pretty strong to me.  I agree
> with David that the #keyPath syntax makes it feel more like a second class
> citizen, not just because of the verbosity but also because it is directly
> borrowed from an Objective-C interop feature.  This is a very powerful
> feature that deserves to be a first class syntactic citizen every bit as
> much as unbound methods do.
>
>>
>> David.
>>
>>>> On Mar 29, 2017, at 2:49 PM, Douglas Gregor <dgregor at apple.com
>>>> <mailto:dgregor at apple.com>> wrote:
>>>>
>>>>
>>>>> On Mar 17, 2017, at 10:04 AM, 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:
>>>>
>>>>
>>>> The Swift core team discussed this proposal draft and had a little bit
>>>> of pre-review feedback.
>>>>
>>>>> Access and Mutation Through KeyPaths
>>>>>
>>>>> To get or set values for a given root and key path we effectively add
>>>>> the following subscripts to all Swift types.
>>>>>
>>>>> Swift
>>>>> |extension Any { subscript(path: AnyKeyPath) -> Any? { get }
>>>>> subscript<Root: Self>(path: PartialKeyPath<Root>) -> Any { get }
>>>>> subscript<Root: Self, Value>(path: KeyPath<Root, Value>) -> Value {
>>>>> get } subscript<Root: Self, Value>(path: WritableKeyPath<Root, Value>)
>>>>> -> Value { set, get } }|
>>>>
>>>> Swift doesn’t currently have the ability to extend Any, so this is
>>>> (currently) pseudocode for compiler magic that one day we might be able
>>>> to place. Additionally, the “Root: Self” constraint isn’t something we
>>>> support in the generics system. A small note indicating that this is
>>>> pseudo-code meant to get the point across (rather than real code to
>>>> drop into the standard library/Foundation) would be appreciated.
>>>>
>>>> More importantly, this adds an unlabeled subscript to every type, which
>>>> raises concerns about introducing ambiguities—even if not hard
>>>> ambiguities that prevent code from compiling (e.g., from a
>>>> Dictionary<AnyKeyPath, …>)---they can still show up in code completion,
>>>> diagnostics, etc.
>>>>
>>>> The core team would prefer that this subscript distinguish itself more,
>>>> e.g., by labeling the first parameter “keyPath” (or some better name,
>>>> if there is one). Syntactically, that would look like:
>>>>
>>>> person[keyPath: theKeyPathIHave]
>>>>
>>>>> Referencing Key Paths
>>>>>
>>>>> Forming a |KeyPath| borrows from the same syntax used to reference
>>>>> methods and initializers,|Type.instanceMethod| only now working for
>>>>> properties and collections. Optionals are handled via
>>>>> optional-chaining. Multiply dotted expressions are allowed as well,
>>>>> and work just as if they were composed via the |appending| methods
>>>>> on |KeyPath|.
>>>>>
>>>> The core team was concerned about the use of the Type.instanceProperty
>>>> syntax for a few reasons:
>>>>
>>>> * It doesn’t work for forming keypaths to class/static properties (or
>>>> is ambiguous with the existing meaning(, so we would need another
>>>> syntax to deal with that case
>>>> * It’s quite subtle, even more so that the existing Type.instanceMethod
>>>> syntax for currying instance methods
>>>>
>>>>> There is no change or interaction with the #keyPath() syntax
>>>>> introduced in Swift 3.
>>>>>
>>>> The core team felt that extending the #keyPath syntax was a better
>>>> syntactic direction to produce key-paths.
>>>>
>>>> - Doug
>>>>
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>


More information about the swift-evolution mailing list