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>:
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 Tovar transform: (From) -> To { get }
}extension KeyPath: TransformConvertible {
public typealias From = Root
public typealias To = Valuepublic 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> 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/863916921577758721But 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> 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> 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> 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> wrote:
On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution < > 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
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
_______________________________________________
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_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution