Ah, quite ingenious, Susan! And you made me realize that the only reason my no-operator-needed code didn’t compile is that I had keypath instead of keyPath. So it was indeed “Paul needs to go to sleep now” option, which I will now do. 🙄
P > On Jun 7, 2017, at 11:34 PM, Susan Cheng <susan.dog...@gmail.com> wrote: > > this work, > > prefix operator * > > prefix func *<Root, Value>(keyPath: KeyPath<Root, Value>) -> (Root) -> Value { > return { $0[keyPath: keyPath] } > } > > ["Hello, World"].map(*\String.count) // [12] > > > 2017-06-08 12:19 GMT+08:00 Paul Cantrell via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>: > It should be possible to achieve Ruby-like generality in Swift with a > protocol for “thing that can converted to a transform function.” That > wouldn’t need a special & operator. > > Here’s a sketch. This sketch doesn’t compile — maybe not enough of Swift 4 is > there yet for it to work, or maybe I am missing something obvious and need to > go to sleep now — but it’s close enough to suggest the approach: > > public protocol TransformConvertible { // or whatever you want to call it > associatedtype From > associatedtype To > > var transform: (From) -> To { get } > } > > extension KeyPath: TransformConvertible { > public typealias From = Root > public typealias To = Value > > public var transform: (Root) -> Value { > return { $0[keypath: self] } > } > } > > extension Sequence { > public func map<T, U>(_ transformSource: U) -> [T] > where U: TransformConvertible, > U.From == Element, > U.To == T { > return map(transformSource.transform) > } > } > > This seems a bit more ambitious, perhaps not suitable for this round of Swift > evolution work. But I throw it out there at least to show that supporting > people.map(\.firstName) today would not preclude a generic keypath → function > mechanism in the future: > > A flavor of map that accepts a keypath today could be generalized to accept > TransformConvertible in the future without breaking existing code. > When calling a function that doesn’t know how to work with > TransformConvertible, you could use (Foo.bar).transform, no special operator > needed. > > Cheers, > > Paul > > P.S. Largely irrelevant Ruby aside: Ruby’s & is not a free-floating operator, > but part of the method invocation syntax indicating that the following arg > should be treated as a block. Ruby calls a to_proc method on whatever is in > that position. Symbol implements to_proc by returning a lambda that calls the > method named by the symbol on the lambda’s first arg. Very much the > duck-typed version of TransformConvertible above. > > >> On Jun 7, 2017, at 10:21 PM, Stephen Celis via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >> -1 >> >> A -1 from me may be surprising. I'm excited about key path composition and >> generic solutions, e.g. this experiment with lenses: >> https://twitter.com/stephencelis/status/863916921577758721 >> <https://twitter.com/stephencelis/status/863916921577758721> >> >> But I'd prefer a reusable solution for converting key paths into functions. >> >> Heaven help me for this Rubyism, but a prefix "&" operator (or, maybe better >> yet, some implicit mechanism) could convert a key-path to a function that >> passes a root value to a key path... >> >> people.map(&\.firstName) >> >> This way any function that takes a transformation from "whole" to "part" >> could take a key path. Requiring an overload per instance is less flexible. >> >> Stephen >> >>> On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> +1, I really like this. It would also align nicely with the method type >>> flattening in SE-0042 (once it gets implemented), because passing keypaths >>> (i.e., unbound property references) and unbound parameterless method >>> references to map/flatMap would look nearly the same: >>> >>> ``` >>> struct Person { >>> let firstName: String >>> let lastName: String >>> func fullName() -> String { return "\(firstName) \(lastName)" } >>> } >>> >>> let people: [Person] >>> let firstNames = people.map(\.firstName) >>> let fullNames = people.map(Person.fullName) // because after SE-0042, this >>> will be (Person) -> String, not (Person) -> () -> String >>> ``` >>> >>> Especially if there's a move in the future to also use \. to denote unbound >>> methods references, which was discussed during the keypath reviews. (Even >>> with that, I believe it would be more work though to get rid of the >>> explicit type name in the function case.) >>> >>> >>> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> +1. Would think that all variants should exist on Optional too unless it >>> would be harmful. >>> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> 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 >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>> 💯 >>>> >>>>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution >>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 <mailto:swift-evolution@swift.org> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution> > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution