Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Michael J LeHew Jr via swift-evolution
This is a great idea, and ought to be easy enough to bring forward!  +1 from me!

-Michael

> On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>>  wrote:
>> 
>> The new smart key path feature is really lovely, and feels like a great 
>> addition to Swift.
>> 
>> It seems like it might be straightforward to add overloads of `map` and 
>> `flatMap` to the standard library to make use of the new functionality:
>> 
>>  let managers = flatOrganisation.managers
>>  let allEmployees = Set(managers.flatMap(\.directReports))
>>  let employeeNames = Set(allEmployees.map(\.name))
>> 
>> This feels like a really natural way of working with key paths in a 
>> functional style. It makes a lot of sense for collections, and possibly for 
>> Optional too (although as far as I can see optional chaining is more or less 
>> equivalent, and with more compact syntax).
>> 
>> I’m hoping that this might be low-hanging fruit that could be considered for 
>> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
>> there’s interest!
>> 
>> –Adam
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Returned for revision] SE-0161: Smart KeyPaths: Better Key-Value Coding for Swift

2017-04-06 Thread Michael J LeHew Jr via swift-evolution
\Vector -> Int seems like a more appropriate spelling there no?   The : is 
usually for is-a/conforms-to relationships, no?

And I agree that such a thing could be considered later and would make the 
world a better place.

-Michael

> On Apr 6, 2017, at 4:21 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Apr 6, 2017, at 2:39 PM, Joe Groff via swift-evolution 
>> > wrote:
>> 
>> for key in [\Vector.x, \.y, \.z, \.w] {
>>  a[key] += b[key]
>> }
> 
> Sorry to derail slightly, but I'd love to see a key path type 
> shorthand—perhaps something like:
> 
>   for key: \Vector: Int in [\.x, \.y, \.z, \.w] {
>   …
>   }
> 
> It's probably something we should defer until we know more about how 
> frequently people use key paths, though.
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review #2] SE-0161: Smart KeyPaths: Better Key-Value Coding for Swift

2017-04-06 Thread Michael J LeHew Jr via swift-evolution

> On Apr 6, 2017, at 10:37 AM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
>> On Apr 6, 2017, at 10:28 AM, Ricardo Parada > > wrote:
>> 
>> Do you think in the future it might be possible to convert to strings?  
>> 
>> For example, I am imagining a CoreData-like framework on the server (where 
>> there is no Objective-C), where I would like to get the type of the root 
>> object and keys forming the path.  That way I can go to an object model, get 
>> the corresponding entity, and traversed relationships, and destination 
>> attribute.  All that information (table name, table joins for the 
>> relationships traversed, column names, etc.) would then be used to construct 
>> the SQL.
> 
> Key-paths could be extended to allow introspection of the components along 
> the path, in which case you would be able to map between key paths into your 
> specific data model and the tables/columns in your database. This is not the 

... ?  You left us hanging there Doug! :)

We do mention in the proposal that support for marshalling to external 
representation (String, Codable should that be accepted, etc) would highly 
desirable in the future, for IB / CoreData type scenarios and more.  It is one 
of the principle reasons we decided not to allow key paths to compose with 
transformations (functions and closures), as while that is very powerful and 
interesting, once you go there you're not really a key path any more. 

It's not part of this initial proposal, but could easily be brought up as a 
follow-on in the future. 

-Michael


> 
>   - Doug
> 
>> 
>> 
>> 
>>> On Apr 6, 2017, at 12:37 PM, Douglas Gregor >> > wrote:
>>> 
 
 On Apr 6, 2017, at 9:31 AM, Sean Heber > wrote:
 
 
> On Apr 6, 2017, at 11:19 AM, Douglas Gregor  > wrote:
> 
>> 
>> On Apr 6, 2017, at 8:13 AM, Ricardo Parada via swift-evolution 
>> > wrote:
>> 
>> I agree, there's an analogy between strings and key paths, and in that 
>> regards the single quote would make sense.  I would not complain.  
> 
> The only analogy between strings and key-paths is that the existing Cocoa 
> APIs for key-paths use strings. That’s not an analogy to hang language 
> syntax on, because it’s relevance will fade quickly. 
 
 Why would it fade quickly? Do we expect the concept of keypaths to go away 
 over time? If so, why are we even designing a syntax for keypaths?
>>> 
>>> The link between key-paths and strings will go away over time. The *only* 
>>> reason anyone associates strings with keypaths is because Cocoa’s current 
>>> key-paths are string-based. This proposal makes any string representation 
>>> of key-paths an implementation detail that could be used for 
>>> interoperability with Cocoa’s current system. There is no reason for a 
>>> type-unsafe string representation to ever be in the user model.
>>> 
>>> 
> The core team discussed single quotes, and decided that we want to save 
> them for something in the string/character realm.
 
 Are they to be saved for something specific or is this just because a lot 
 of languages use single quotes for character literals? Why is this 
 association any more sacred than an association with Cocoa string keypaths?
>>> 
>>> 
>>> Lots of languages use single quotes for character literals; we may want to 
>>> bring them back for it.
>>> 
>>> - Doug
>> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0161: Smart KeyPaths: Better Key-Value Coding for Swift

2017-04-05 Thread Michael J LeHew Jr via swift-evolution

> On Apr 3, 2017, at 1:47 PM, Joshua Alvarado via swift-evolution 
>  wrote:
> 
> Example:
> struct Foo {
> var firstName: String
> var lastName: String
> }
> 

You would need to spell out #keyPath(Foo, .firstName) here, or decorate the 
type on keyPaths like so:

let keyPaths : [KeyPath]  = ... or let keyPaths : 
[PartialKeyPath] = ...  to use the short hand in your value declaration.  
The difference between the two is that the PartialKeyPath lets you refer to 
non-string properties, whereas the other is more strongly typed. 

> let keyPaths = [#keyPath(.firstName), #keyPath(.lastName)]

The same would be true on the inference:

> let keyPaths = [#keyPath(Foo, .firstName), #keyPath(Foo, .lastName)]

Infers that keyPaths is a [KeyPath] since everything agrees;

let keyPaths = [#keyPath(Foo, .firstName), #keyPath(Foo, .age)] // suppose it 
returns Int

Would only be able to infer up to PartialKeyPath.

> for key in keyPaths {
> foo[keyPath: key] = "bar"
> }
> 
> print(foo) // firstName = bar, lastName = bar

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Smart KeyPaths

2017-03-29 Thread Michael J LeHew Jr via swift-evolution

> On Mar 29, 2017, at 4:52 PM, Brent Royal-Gordon <br...@architechies.com> 
> wrote:
> 
>> On Mar 29, 2017, at 4:13 PM, Michael J LeHew Jr via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@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?

I had the same reaction initially -- but then after talking with Joe, he 
reminded me that this is the kind of code that only comes up in a 'this is how 
it works' context.  Typically the key path will be a value and the syntax looks 
like:  luke[keyPath: somePath]

That example is a touch contrived to show that we'll be able to do the type 
inference where possible, 

> 
> 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`, `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.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`.
> 
> 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`; 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? 

I'll let Joe speak to this aspect since this touches a lot more on 
implementation. 

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Smart KeyPaths

2017-03-29 Thread Michael J LeHew Jr via swift-evolution

> On Mar 29, 2017, at 5:12 PM, James Berry <jbe...@rogueorbit.com> wrote:
> 
>> Referencing Key Paths
>> 
>> Forming a KeyPath borrows from the same syntax added in Swift 3 to confirm 
>> the existence of a given key path, only now producing concrete values 
>> instead of Strings. 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.
>> 
>> There is no change or interaction with the #keyPath() syntax introduced in 
>> Swift 3. #keyPath(Person.bestFriend.name) will still produce a String, 
>> whereas #keyPath(Person, .bestFriend.name) will produce a KeyPath<Person, 
>> String>.
> 
> This distinction seems arbitrary and confusing. The user is supposed tor 
> remember that the #keyPath(Person.bestFriend.name) form produces a string 
> while the #keyPath(Person, .bestFriend.name) form produces a key path object? 
> I don’t think we’re advancing here. What would be the effect if just the 
> former was valid, and (always/now) produced a keypath object that was 
> convertible to string? How bad would the breakage be?

The syntax subtleties here are unfortunate. 

 An idea that we discussed was to be able to tell when a #keyPath wants to be 
considered as a string and either implicitly or having some affordance for 
doing so.   Back then this was harder because we had #keyPaths that could not 
be represented as a string (an earlier draft had keyPaths that could compose 
with closures; which while powerful, weren't really key paths any more. That 
idea was removed from the proposal we shared as they are intrinsically opposed 
to being able to serializing/deserialize key paths).  

Given that we don't support those kinds of key paths, nor are we really 
considering adding them back thanks to our desire to support serializing key 
paths to file in the future, this is a very reasonable idea I think. 


> 
> James
> 
> 
> 
>> On Mar 29, 2017, at 4:13 PM, Michael J LeHew Jr via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@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>
>> 
>> -Michael
>> 
>>> On Mar 29, 2017, at 2:49 PM, Douglas Gregor <dgre...@apple.com 
>>> <mailto:dgre...@apple.com>> wrote:
>>> 
>>> 
>>>> On Mar 17, 2017, at 10:04 AM, Michael LeHew via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@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(path: PartialKeyPath) -> Any { get }
>>>> subscript(path: KeyPath<Root, Value>) -> Value { 
>>>> get }
>>>> subscript(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 “keyP

Re: [swift-evolution] Smart KeyPaths

2017-03-29 Thread Michael J LeHew Jr via swift-evolution
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

> On Mar 29, 2017, at 2:49 PM, Douglas Gregor  wrote:
> 
> 
>> On Mar 17, 2017, at 10:04 AM, Michael LeHew via swift-evolution 
>> > 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(path: PartialKeyPath) -> Any { get }
>> subscript(path: KeyPath) -> Value { get }
>> subscript(path: WritableKeyPath) -> 
>> 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 …>)---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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution