<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 10. Jun 2017, at 01:42, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On 8. Jun 2017, at 04:58, Tony Allevato via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">+1, I really like this. It would also align nicely with the method type flattening in<span class="Apple-converted-space">&nbsp;</span><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0042-flatten-method-types.md" class="">SE-0042</a><span class="Apple-converted-space">&nbsp;</span>(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:<br class=""><div class=""><br class=""></div><div class="">```</div><div class="">struct Person {</div><div class="">&nbsp; let firstName: String</div><div class="">&nbsp; let lastName: String</div><div class="">&nbsp; func fullName() -&gt; String { return "\(firstName) \(lastName)" }</div><div class="">}</div><div class=""><br class=""></div><div class="">let people: [Person]</div><div class="">let firstNames = people.map(\.firstName)</div><div class="">let fullNames = people.map(Person.fullName) &nbsp;// because after SE-0042, this will be (Person) -&gt; String, not (Person) -&gt; () -&gt; String</div><div class="">```</div><div class=""><br class=""></div><div class="">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.)</div><div class=""><br class=""></div></div><br class=""></div></blockquote><div class=""><br class=""></div><div class="">When it comes to unbound method references, personally, I would love to see us ditch currying in some future version of Swift and move to full-blown partial application instead. We would need variadic generics if we wanted to expose them as nicely-typed objects as we do with KeyPaths.</div><div class=""><br class=""></div><div class="">Anyway, I think what you want is something like this (where VirtualKeyPath is a custom subclass of KeyPath which is lazily-evaluated using a closure).</div><div class=""><br class=""></div></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><font face="Menlo" class="">extension KeyPath where Value: Collection {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; func map&lt;T&gt;(_ descendent: KeyPath&lt;Value, T&gt;) -&gt; VirtualKeyPath&lt;Root, [T]&gt; {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; return VirtualKeyPath&lt;Root, [T]&gt; {&nbsp;</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (obj: Root) -&gt; [T] in obj[keypath: self].map { $0[keypath: descendent] }&nbsp;</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">\Department.people.map(\.fullName).characters.count &nbsp;// type: VirtualKeyPath&lt;Department, [Int]&gt;</font></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Custom subclasses of KeyPath are not allowed, so you can’t actually do this. I don’t know, maybe it wouldn’t be much overhead to add the one, closure-based VirtualKeyPath — clearly the architecture is meant to be flexible. Maybe it’s better to wait until Swift 5 for that, though.</div><div class=""><br class=""></div><div class="">- Karl</div></div></div></blockquote><div><br class=""></div><div>Two corrections to myself:</div><div><br class=""></div><div>1) It’s KeyPath&lt;Value.Element, T&gt;</div><div><br class=""></div><div>2) You could implement VirtualKeyPath today, but you wouldn’t get the chaining syntax. You’d have to just keep map-ping it every time:</div><div><br class=""></div><div><font face="Menlo" class="">\Department.people.map(\.fullName).map(\.characters.count) &nbsp;// type: VirtualKeyPath&lt;Department, [Int]&gt;</font></div><div><br class=""></div><div>- Karl</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class="gmail_quote"><div dir="ltr" class="">On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">+1. Would think that all variants should exist on Optional too unless it would be harmful.<br class=""><div class="gmail_quote"><div dir="ltr" class="">On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">This is a great idea, and ought to be easy enough to bring forward!&nbsp; +1 from me!<br class=""><br class="">-Michael<br class=""><br class="">&gt; On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">&gt;<br class="">&gt; 💯<br class="">&gt;<br class="">&gt;&gt; On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">&gt;&gt;<br class="">&gt;&gt; The new smart key path feature is really lovely, and feels like a great addition to Swift.<br class="">&gt;&gt;<br class="">&gt;&gt; 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:<br class="">&gt;&gt;<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp; let managers = flatOrganisation.managers<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp; let allEmployees = Set(managers.flatMap(\.directReports))<br class="">&gt;&gt;&nbsp; &nbsp; &nbsp; let employeeNames = Set(allEmployees.map(\.name))<br class="">&gt;&gt;<br class="">&gt;&gt; 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).<br class="">&gt;&gt;<br class="">&gt;&gt; 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!<br class="">&gt;&gt;<br class="">&gt;&gt; –Adam<br class="">&gt;&gt;<br class="">&gt;&gt; _______________________________________________<br class="">&gt;&gt; swift-evolution mailing list<br class="">&gt;&gt;<span class="Apple-converted-space">&nbsp;</span><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">&gt;&gt;<span class="Apple-converted-space">&nbsp;</span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">&gt;<br class="">&gt; _______________________________________________<br class="">&gt; swift-evolution mailing list<br class="">&gt;<span class="Apple-converted-space">&nbsp;</span><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">&gt;<span class="Apple-converted-space">&nbsp;</span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div></div></blockquote></div><br class=""></body></html>