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
> <[email protected]> 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
>
> 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
>> <[email protected]> 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
>> <[email protected]> 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
>> <[email protected]> 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
>>> <[email protected]> wrote:
>>>
>>> 💯
>>>
>>>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution
>>>> <[email protected]> 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
>>>> [email protected]
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution