> On Apr 6, 2017, at 3:05 PM, Matthew Johnson <[email protected]> wrote:
> 
> 
>> On Apr 6, 2017, at 1:21 PM, John McCall <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> On Apr 6, 2017, at 2:12 PM, Matthew Johnson <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>>> On Apr 6, 2017, at 1:06 PM, John McCall <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>>> On Apr 6, 2017, at 1:41 PM, Matthew Johnson <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>>> On Apr 6, 2017, at 12:32 PM, John McCall <[email protected] 
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>>> On Apr 5, 2017, at 9:46 PM, Matthew Johnson via swift-evolution 
>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>> On Apr 5, 2017, at 7:32 PM, David Smith via swift-evolution 
>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>> 
>>>>>>>> The rationale for using the same syntax is that a KeyPath is an 
>>>>>>>> unapplied property/subscript access. Even the multi-segment part of it 
>>>>>>>> isn't necessarily dissimilar: I don't think it would be unreasonable 
>>>>>>>> to imagine that \Foo.someMethod.someOtherMethod could work*, that'd 
>>>>>>>> just be function composition after all.
>>>>>>>> 
>>>>>>>> KeyPath : Properties/Subscripts :: Functions with a self argument : 
>>>>>>>> Methods
>>>>>>>> 
>>>>>>>>        David
>>>>>>>> 
>>>>>>>> *not proposing this, haven't thought carefully about whether there are 
>>>>>>>> edge cases I'm missing here, but I think the analogy holds
>>>>>>> 
>>>>>>> I alluded to this kind of thing in the earlier threads.  It would be 
>>>>>>> very cool to see this explored in the future.
>>>>>>> 
>>>>>>> I really like the latest draft and am eagerly anticipating Smart 
>>>>>>> KeyPaths being implemented.  Thank you for listening to feedback from 
>>>>>>> the community!
>>>>>>> 
>>>>>>> One possible future direction I have been wondering about is whether it 
>>>>>>> might be interesting to expose an anonymous type for each distinct key 
>>>>>>> path which would have static members for getting (and setting if 
>>>>>>> mutable) the value.  The types would inherit from the most specific 
>>>>>>> matching key path type included in this proposal.  This would allow us 
>>>>>>> pass key paths statically using the type system and therefore not 
>>>>>>> requiring any runtime overhead.  
>>>>>>> 
>>>>>>> I have experimented with this approach in some of my own code and it 
>>>>>>> looks like it would be a very promising approach aside from the 
>>>>>>> boilerplate required to write these types manually.  I have abandoned 
>>>>>>> this approach for now because of the boilerplate and because the 
>>>>>>> syntactic sugar of the key path shorthand in this proposal is too 
>>>>>>> attractive to pass up.  I would love to explore it again in the future 
>>>>>>> if key paths were to support this approach.
>>>>>> 
>>>>>> Our generics system does not require generic code to be de-genericized 
>>>>>> ("instantiated" in C++ terminology, "monomorphized" in Rust, etc.) in 
>>>>>> order to be run.  The generic code for applying a value of an unknown 
>>>>>> key-path type would look exactly like the non-generic code for applying 
>>>>>> a dynamic key-path type.  To get a runtime benefit, the compiler would 
>>>>>> have to de-genericize all the code between the function that formed the 
>>>>>> concrete key path and the function that applied it.  If the compiler can 
>>>>>> do that, it can also specialize that code for a known key path argument, 
>>>>>> the same way that it can specialize a function for a known function 
>>>>>> argument.  So there's no point.
>>>>> 
>>>>> Thanks for the reply John.  There may not be any additional optimization 
>>>>> opportunities in terms of code generation when using the key path but 
>>>>> wouldn’t it save on storage and reference counting related to key path 
>>>>> value?
>>>> 
>>>> If you're specializing all the way down, any sort of boxing should be 
>>>> possible to eliminate as well.
>>>> 
>>>> If you mean in unspecialized code, well, I'm not entirely sure what 
>>>> representation Joe is using, but I would assume that the fast path — where 
>>>> a key path doesn't capture anything — does not require any allocation.  In 
>>>> that sense, there's a strong parallel with how we represent functions: 
>>>> yes, avoiding an extra allocation would be nice, but if you're willing to 
>>>> accept an occasional allocation in more complex cases, there are also a 
>>>> lot of benefits from being able to always give the type a concrete, 
>>>> fixed-size representation.
>>> 
>>> Key paths in this proposal are classes which require storage of the pointer 
>>> as well as reference counting unless there is special of key path values.  
>>> Is something like that planned?  I could imagine some kind of tagged 
>>> pointer might be possible but I can’t imagine how you would eliminate the 
>>> need to store a word.  It’s not that much overhead but it would still be 
>>> nice to be able to avoid it when all we’re doing is passing a stateless 
>>> function reference.
>> 
>> Are you under the impression that run-time generics don't require passing 
>> extra pointers around?
> 
> It’s quite possible there is something I don’t understand correctly.  Let’s 
> look at a concrete example.
> 
> struct UsesKeyPath {
>     let keyPath: KeyPath<MyModel, MyValue>
> }
> 
> struct UsesKeyPath<T: KeyPath<MyModel, MyValue>> {}
> 
> Is there a difference in the storage required for these two structs?  If 
> there isn’t then I have something to learn! :)  I guess my assumption is that 
> the second struct would have zero size because it has no stored properties 
> but maybe that is incorrect.

Well, these aren't equivalent, because the second doesn't actually store a key 
path.  You're assuming that key paths never involve storage, which is not 
correct, because they can capture subscript indices.  The equivalent type would 
be:

struct UsesKeyPath<T: KeyPath<MyModel, MyValue>> {
  let keyPath: T
}

Now, there would be a difference in the storage required for these two structs, 
because presumably a value of a concrete key-path type just stores whatever 
data is captured for the key path, which in most cases would be nothing, and 
the information about what key-path it actually is would be stored in the type 
object for UsesKeyPath<T>.  But, of course, you really do need that information 
in order to do anything with UsesKeyPath<T>, so all of the methods on it would 
require that type object to be passed in, which is something you can skip with 
the non-generic version.  And the fact that the layout of this struct varies 
depending on T means that everything written in terms of it gets a lot more 
complicated unless specialized for a concrete key path type.  So it would be a 
trade-off between the storage size of UsesKeyPath and the code-size overhead of 
every operation on it.

Plus, of course, supporting all these key-path types would be a ton of 
complexity throughout the language and its implementation, because most uses of 
key paths cannot be type-parametric like this and so you would still need the 
erased KeyPath<A, T> type; and like I said, the dominant cases would still be 
just as optimizable with that erased type.

John.

> 
>> 
>> John.
>> 
>>> 
>>>> 
>>>>> As a secondary question, wouldn’t this be similar to the difference 
>>>>> between generics and existentials?  In theory the same optimizations 
>>>>> could be applied but in practice they are not always right now.  Is the 
>>>>> plan to eventually put existentials on equal footing in terms of 
>>>>> optimization?
>>>> 
>>>> Eventually, yes, I think that's something we'd like make sure we can do.
>>>> 
>>>> John.
>>>> 
>>>>> 
>>>>>> 
>>>>>> John.
>>>>>> 
>>>>>>> 
>>>>>>> Matthew
>>>>>>> 
>>>>>>>> 
>>>>>>>>> On Apr 5, 2017, at 5:16 PM, Patrick Smith via swift-evolution 
>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>> 
>>>>>>>>> I too find the backslash odd, as it’s usually of course used to 
>>>>>>>>> escape something.
>>>>>>>>> 
>>>>>>>>> What about three periods?
>>>>>>>>> 
>>>>>>>>> let firstFriendsNameKeyPath = Person...friends[0].name
>>>>>>>>> print(luke[keyPath: ...friends[0].name])
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> I also find wanting to use the same syntax for unapplied methods 
>>>>>>>>> strange, as they would product two totally different things: one a 
>>>>>>>>> key path value, the other a function.
>>>>>>>>> 
>>>>>>>>> Patrick
>>>>>>>>> On Thu, 6 Apr 2017 at 10:00 am, Douglas Gregor via swift-evolution 
>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>>> On Apr 5, 2017, at 4:55 PM, Colin Barrett 
>>>>>>>>>> <[email protected] <mailto:[email protected]>> 
>>>>>>>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>> Is the choice of backslash up for review? I think another operator, 
>>>>>>>>> 
>>>>>>>>> We talked through basically everything on the keyboard, and there 
>>>>>>>>> really aren’t other options that don’t stomp on existing behavior.
>>>>>>>>> 
>>>>>>>>>> perhaps backtick (`), would work better. 
>>>>>>>>> 
>>>>>>>>> Backtick (`) is already taken for escaping identifiers, e.g., 
>>>>>>>>> 
>>>>>>>>>       var `func` = { /* some code */ }
>>>>>>>>> 
>>>>>>>>>       - Doug
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> _______________________________________________
>>>>>>>>> swift-evolution mailing list
>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>> _______________________________________________
>>>>>>>>> swift-evolution mailing list
>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>> 
>>>>>>>> _______________________________________________
>>>>>>>> swift-evolution mailing list
>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>> 
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to