[swift-evolution] Smart KeyPaths

Vladimir.S svabox at gmail.com
Wed Mar 22 12:34:49 CDT 2017


On 22.03.2017 19:25, Matthew Johnson wrote:
>
>> On Mar 22, 2017, at 11:00 AM, Vladimir.S <svabox at gmail.com
>> <mailto:svabox at gmail.com>> wrote:
>>
>> On 22.03.2017 18:47, Matthew Johnson wrote:
>>>
>>>> On Mar 22, 2017, at 10:36 AM, Vladimir.S via swift-evolution
>>>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> <mailto:swift-evolution at swift.org>> wrote:
>>>>
>>>> On 22.03.2017 17:37, Ricardo Parada wrote:
>>>>>
>>>>>
>>>>>> On Mar 22, 2017, at 9:30 AM, Vladimir.S <svabox at gmail.com
>>>>>> <mailto:svabox at gmail.com>
>>>>>> <mailto:svabox at gmail.com>> wrote:
>>>>>>
>>>>>> let path = @Bag.things[0].name
>>>>>>
>>>>>> bag at path
>>>>>> bag at .things[0].name
>>>>>> bag at Bag.things <mailto:bag at Bag.things> <mailto:bag at Bag.things>[0].name
>>>>>> bag.things[0]@.name
>>>>>> bag.things[0]@Thing.name
>>>>>
>>>>> It sounds like the @ character is serving two different purposes which
>>>>> confused me at first.
>>>>>
>>>>> If I understood correctly, you are using it to get the key path but also
>>>>> to apply the key path to the bag struct and get the corresponding value.
>>>>>
>>>>
>>>> Yes. And the initial proposal suggest the following syntax accordingly:
>>>>
>>>> let path = Bag.things[0].name
>>>> bag[path]
>>>> bag[.things[0].name]
>>>> bag[Bag.things[0].name]
>>>> bag.things[0][.name]
>>>> bag.things[0][Thing.name]
>>>
>>> # makes a lot more sense than @ as a sigil.  It follows from #selector and
>>> #keyPath.  These are the most similar language features right now where the
>>> compiler produces special values.  I think it’s also worth noticing that
>>> values produced by #selector and #keyPath are /used/ in normal ways.  There
>>> is no magic syntax for their use, just a typed value.  If we’re going to
>>> make a change we should use # instead of `.` for accessing these special
>>> values but we should stick with subscript for use.
>>
>> Could you clarify, what do you suggest? Something like this:
>> let path = Bag#things[0]#name
>
> I would only use one # at the start of the key path.  Dots could be used
> afterwords like this: `Bag#things[0].name`  I think it is important to use
> normal expression syntax after the key path is introduced.
>

Generally agree.

>> bag[#path]
>
> No, you would just say `bag[path]`.  `path` is a normal value and the
> subscript taking a path is a normal subscript.

That was my main intention - to discuss if we should add some special 
marker when we create *and* also use key path. To remove confusion when you 
see 'instance[something]' in one's code and can't be sure if we access a 
"normal" subscript or 'something' is a key path. Especially if instance is 
array/dictionary or other collection.
I believe this feature deserves some highlighting with special syntax even 
on usage site.
And subscript in this case IMO is not "normal" subscript - but "special" 
subscript generated by compiler to work with key path.


Vladimir.

>
>> bag[#things[0]#name]
>
> Here we have a type context expecting a key path with a root of the type of
> `bag`.  There is no potential ambiguity involved in using the `.` here
> unless people extend the key path types with static members themselves.  I
> think it’s fair to say do that at your own risk.  So there is no *need* to
> use special synatx - dot shorthand would work just fine with no ambiguity
> problem.  You could imagine the compiler synthesizing static members on key
> path types like this:
>
> extension PartialKeyPath where Root == BagType {
>     static var things: KeyPath<Root, ThingsType>  // or WriteableKeyPath
> or ReferenceWritableKeyPath
> }
>
> You just say: `bag[.things[0]#name]` using the existing dot shorthand for
> static members that return a value matching the type they are declared on.
>
> On the other hand, it would be more consistent to introduce # shorthand
> here and not have the imaginary / synthesized static members on the key
> path types.  I’m neutral, leaning towards using # shorthand for this.
>
>
>> bag[Bag#things[0]#name]
>
> As above, there is no need for a second `#`.  Once the expression has
> produced a key path all subsequent chained accesses will also produce a key
> path.
>
> bag[Bag#things[0].name]
>
>> bag.things[0][#name]
>
> As above, here we have a type context in the subscript that expects a key
> path.  We could use the existing dot shorthand and compiler synthesized
> static properties on key path types or just introduce a # shorthand.  The
> latter is probably better for consistency.
>
>> bag.things[0][Thing#name]
>
> Sure, if you don’t like the shorthand.
>
>>
>> ,and so
>> let ref = Bag#foo()
>
> Yep.
>
> One interesting thing to note is that we could also get deep references to
> unbound methods.  This would effectively combine key paths with unbound
> method references:
>
> let doSomething = Bag#things[0].doSomething()
>
> used like this:
> doSomthing(bag)
>
> Using # for key paths also allows us to build on it in the future for
> collection operators:
>
> Bag#things[#sum].value //  a key path that sums the value of all things in
> a bag
>
> Reserving this potential is one important reason to only use # where you
> are introducing a special key path expression and not everywhere in the key
> path chain.
>
>>
>> ?
>>
>> In this case I feel like the following will be more clean syntax:
>> let path = #Bag.things[0].name
>> bag[#path]
>> bag[#.things[0].name]
>> bag[#Bag.things[0].name]
>> bag.things[0][#.name]
>> bag.things[0][#Thing.name]
>> let ref = #Bag.foo()
>
> This is kind of weird because Bag doesn’t have a static things property.  I
> think it’s better to start put the # in the middle.  That said, this would
> work as well.
>
>>
>> And why subscript is the only good candidate for use?
>
> It is how Swift models parameterized value access.  Building on that model
> makes a ton of sense.  I can’t imagine a compelling argument for
> /using/ key path values.
>
>> Actually, for me personally, any solution will be good as soon as it
>> contains some 'marker' which saying "hey, here key paths are used. be aware."
>>
>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> <mailto:swift-evolution at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>


More information about the swift-evolution mailing list