<div dir="ltr">this work,<div><p style="margin:0px;font-size:12px;line-height:normal;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)">prefix<span style="color:rgb(0,0,0)"> </span>operator<span style="color:rgb(0,0,0)"> *</span></p>
<p style="margin:0px;font-size:12px;line-height:normal;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,0,0)"><span style="color:rgb(186,45,162)">prefix</span> <span style="color:rgb(186,45,162)">func</span> *&lt;Root, Value&gt;(keyPath: <span style="color:rgb(112,61,170)">KeyPath</span>&lt;<span style="color:rgb(79,129,135)">Root</span>, <span style="color:rgb(79,129,135)">Value</span>&gt;) -&gt; (<span style="color:rgb(79,129,135)">Root</span>) -&gt; <span style="color:rgb(79,129,135)">Value</span> {</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,0,0)">    <span style="color:rgb(186,45,162)">return</span> { $0[keyPath: keyPath] }</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,0,0)">}</p>
<p style="margin:0px;font-size:12px;line-height:normal;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,0,0)">[<span style="color:rgb(209,47,27)">&quot;Hello, World&quot;</span>].<span style="color:rgb(62,30,129)">map</span>(*\<span style="color:rgb(112,61,170)">String</span>.count)    <span style="color:rgb(0,132,0)">// [12]</span></p></div><div><span style="color:rgb(0,132,0)"><br></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">2017-06-08 12:19 GMT+08:00 Paul Cantrell via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>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 &amp; operator.</div><div><br></div><div>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:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><div style="margin:0px;line-height:normal">    <span style="color:#323e7d">public</span> <span style="color:#323e7d">protocol</span> TransformConvertible {  // or whatever you want to call it</div><div style="margin:0px;line-height:normal;color:rgb(50,62,125)"><span style="color:#000000">      </span>associatedtype<span style="color:#000000"> From</span></div><div style="margin:0px;line-height:normal;color:rgb(50,62,125)"><span style="color:#000000">      </span>associatedtype<span style="color:#000000"> To</span></div><p style="margin:0px;line-height:normal;min-height:13px">      <br class="m_2164541534149277173webkit-block-placeholder"></p><div style="margin:0px;line-height:normal">      <span style="color:#323e7d">var</span> transform: (<span style="color:#587ea8">From</span>) -&gt; <span style="color:#587ea8">To</span> { <span style="color:#323e7d">get</span> }</div><div style="margin:0px;line-height:normal">    }</div><div style="margin:0px;font-size:12px;line-height:normal;font-family:Helvetica;min-height:14px"><br></div><div style="margin:0px;line-height:normal;color:rgb(88,126,168)"><span style="color:#000000">    </span><span style="color:#323e7d">extension</span><span style="color:#000000"> </span>KeyPath<span style="color:#000000">: </span>TransformConvertible<span style="color:#000000"> {</span></div><div style="margin:0px;line-height:normal;color:rgb(50,62,125)"><span style="color:#000000">      </span>public<span style="color:#000000"> </span>typealias<span style="color:#000000"> From = </span><span style="color:#587ea8">Root</span></div><div style="margin:0px;line-height:normal;color:rgb(50,62,125)"><span style="color:#000000">      </span>public<span style="color:#000000"> </span>typealias<span style="color:#000000"> To = </span><span style="color:#587ea8">Value</span></div><p style="margin:0px;line-height:normal;min-height:13px">      <br class="m_2164541534149277173webkit-block-placeholder"></p><div style="margin:0px;line-height:normal">      <span style="color:#323e7d">public</span> <span style="color:#323e7d">var</span> transform: (<span style="color:#587ea8">Root</span>) -&gt; <span style="color:#587ea8">Value</span> {</div><div style="margin:0px;line-height:normal">        <span style="color:#323e7d">return</span> { $0[keypath: <span style="color:#323e7d">self</span>] }</div><div style="margin:0px;line-height:normal">      }</div><div style="margin:0px;line-height:normal">    }</div><div style="margin:0px;font-size:12px;line-height:normal;font-family:Helvetica;min-height:14px"><br></div><div style="margin:0px;line-height:normal;color:rgb(50,62,125)"><span style="color:#000000">    </span>extension<span style="color:#000000"> </span><span style="color:#587ea8">Sequence</span><span style="color:#000000"> {</span></div><div style="margin:0px;line-height:normal">      <span style="color:#323e7d">public</span> <span style="color:#323e7d">func</span> map&lt;T, U&gt;(<span style="color:#323e7d">_</span> transformSource: <span style="color:#587ea8">U</span>) -&gt; [<span style="color:#587ea8">T</span>]</div><div style="margin:0px;line-height:normal;color:rgb(88,126,168)"><span style="color:#000000">           </span><span style="color:#323e7d">where</span><span style="color:#000000"> </span>U<span style="color:#000000">: </span>TransformConvertible<span style="color:#000000">,</span></div><div style="margin:0px;line-height:normal">                 <span style="color:rgb(88,126,168)">U</span>.<span style="color:#587ea8">From</span> == <span style="color:#587ea8">Element</span>,</div><div style="margin:0px;line-height:normal">                 <span style="color:rgb(88,126,168)">U</span>.<span style="color:#587ea8">To</span> == <font color="#587ea8">T </font>{</div><div style="margin:0px;line-height:normal">        <span style="color:#323e7d">return</span> <span style="color:#587ea8">map</span>(transformSource.<span style="color:#587ea8">transform</span>)</div><div style="margin:0px;line-height:normal">      }</div><div style="margin:0px;line-height:normal">    }</div><div><br></div></div></div><div>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 <span style="font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)">people.map(\.<wbr>firstName)</span> today <b>would not preclude</b> a generic keypath → function mechanism in the future:</div><div><br></div><div><ul class="m_2164541534149277173MailOutline"><li>A flavor of map that accepts a keypath today could be generalized to accept TransformConvertible in the future without breaking existing code.</li><li>When calling a function that doesn’t know how to work with TransformConvertible, you could use (Foo.bar).transform, no special operator needed.</li></ul></div><div><br></div><div>Cheers,</div><div><br></div><div>Paul</div><div><br></div><div><div>P.S. Largely irrelevant Ruby aside: Ruby’s &amp; 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.</div></div><div><br></div><br><div><blockquote type="cite"><div>On Jun 7, 2017, at 10:21 PM, Stephen Celis via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_2164541534149277173Apple-interchange-newline"><div><div>-1<br><br>A -1 from me may be surprising. I&#39;m excited about key path composition and generic solutions, e.g. this experiment with lenses: <a href="https://twitter.com/stephencelis/status/863916921577758721" target="_blank">https://twitter.com/<wbr>stephencelis/status/<wbr>863916921577758721</a><br><br>But I&#39;d prefer a reusable solution for converting key paths into functions.<br><br>Heaven help me for this Rubyism, but a prefix &quot;&amp;&quot; 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...<br><br>   people.map(&amp;\.firstName)<br><br>This way any function that takes a transformation from &quot;whole&quot; to &quot;part&quot; could take a key path. Requiring an overload per instance is less flexible.<br><br>Stephen<br><br><blockquote type="cite">On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br>+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:<br><br>```<br>struct Person {<br>  let firstName: String<br>  let lastName: String<br>  func fullName() -&gt; String { return &quot;\(firstName) \(lastName)&quot; }<br>}<br><br>let people: [Person]<br>let firstNames = people.map(\.firstName)<br>let fullNames = people.map(Person.fullName)  // because after SE-0042, this will be (Person) -&gt; String, not (Person) -&gt; () -&gt; String<br>```<br><br>Especially if there&#39;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.)<br><br><br>On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br>+1. Would think that all variants should exist on Optional too unless it would be harmful.<br>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">swift-evolution@swift.org</a>&gt; wrote:<br>This is a great idea, and ought to be easy enough to bring forward!  +1 from me!<br><br>-Michael<br><br><blockquote type="cite">On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br>💯<br><br><blockquote type="cite">On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br>The new smart key path feature is really lovely, and feels like a great addition to Swift.<br><br>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><br>     let managers = flatOrganisation.managers<br>     let allEmployees = Set(managers.flatMap(\.<wbr>directReports))<br>     let employeeNames = Set(allEmployees.map(\.name))<br><br>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><br>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><br>–Adam<br><br>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></blockquote><br>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></blockquote><br>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></blockquote><br>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></div></blockquote></div><br></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>