<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-06-05 2:16 GMT+09:00 Chris Lattner 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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><span class="gmail-"><br><div><blockquote type="cite"><div>On Jun 1, 2017, at 3:06 PM, John McCall via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="gmail-m_6573092857644974193Apple-interchange-newline"><div><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On Jun 1, 2017, at 2:39 PM, Pavol Vaskovic &lt;<a href="mailto:pali@pali.sk" target="_blank">pali@pali.sk</a>&gt; wrote:</div><br class="gmail-m_6573092857644974193Apple-interchange-newline"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Jun 1, 2017 at 8:52 PM, John McCall via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
I understand that there are developers who dislike SE-0110&#39;s impact on certain kinds of functional programming, but that is a very broad complaint that is unlikely to reach consensus or acceptance, especially for Swift 4.  </blockquote><div><br></div><div>The impact of SE-0110 as currently implemented in Swift 4 leads to following migration choice wherever you have a closure that takes tuple argument:</div><div>* concise but obfuscate code ($0.1, ...)</div><div>* readable but verbose code (requiring a ton of boilerplate: intermediate argument, expand signature to include return type, desctructure tuple on new line using let, add return clause)</div><div><br></div><div>Maybe I misunderstood you, but I don&#39;t think this is marginal issue affecting only some &quot;developers that dislike the impact on certain kinds of functional programming&quot;. </div></div></div></div></div></blockquote><div><br></div>You&#39;re misunderstanding me.  I have explicitly said, several times, that I agree that the impact on tuple destructuring in closures is a serious regression.  There have *also* been objections to losing argument-splat behavior, and while that does negatively affect some functional styles, I think it would be a mistake to try to address that now.</div></div></div></blockquote><br></div></span><div>I agree with both points: we need to fix the type checker semantics+performance regression, but I also sympathize with the beauty regression for closures.  Here are some the examples Gwendal RouĂ© cited up-thread (just to make the discussion concrete):</div><span class="gmail-"><div><br></div><div>Example 1<br>-        return columns.index { (column, _) in column.lowercased() == lowercaseName }<br>+        return columns.index { $0.0.lowercased() == lowercaseName }<br><br>Example 2 :<br>-            .map { (mappedColumn, baseColumn) -&gt; (Int, String) in<br>+            .map { (pair) -&gt; (Int, String) in<br>+                let mappedColumn = pair.key<br>+                let baseColumn = pair.value<br><br>Example 3 :<br>-                .map { (table, columns) in &quot;\(table)(\(columns.sorted().<wbr>joined(separator: &quot;, &quot;)))&quot; }<span class="gmail-m_6573092857644974193Apple-tab-span" style="white-space:pre-wrap">        </span><span class="gmail-m_6573092857644974193Apple-tab-span" style="white-space:pre-wrap">        </span><br>+                .map { &quot;\($0.key)(\($0.value.sorted()<wbr>.joined(separator: &quot;, &quot;)))&quot; }<br><br>Example 4 :<br>-                dictionary.<wbr>first { (column, value) in column.lowercased() == orderedColumn.lowercased() }<br>+                dictionary.<wbr>first { $0.key.lowercased() == orderedColumn.lowercased() }<br><br></div><div><br></div><div><br></div><br></span><div>One way to split the difference here is to eliminate the splatting behavior, but keep the destructuring (irrefutable pattern matching) behavior as well.  In these cases, just require an extra explicit paren for the parameter list.  This would change the diff&#39;s to:</div><div><br></div><div><span class="gmail-">Example 1<br>-        return columns.index { (column, _) in column.lowercased() == lowercaseName }<br></span>+       return columns.index { ((column, _)) in column.lowercased() == lowercaseName }<span class="gmail-"><br><br>Example 2 :<br>-            .map { (mappedColumn, baseColumn) -&gt; (Int, String) in<br></span>+            .map { ((mappedColumn, baseColumn)) -&gt; (Int, String) in<span class="gmail-"><br><br>Example 3 :<br>-                .map { (table, columns) in &quot;\(table)(\(columns.sorted().<wbr>joined(separator: &quot;, &quot;)))&quot; }<span class="gmail-m_6573092857644974193Apple-tab-span" style="white-space:pre-wrap">        </span><span class="gmail-m_6573092857644974193Apple-tab-span" style="white-space:pre-wrap">        </span><br></span>+                .map { ((table, columns)) in &quot;\(table)(\(columns.sorted().<wbr>joined(separator: &quot;, &quot;)))&quot; }<span class="gmail-m_6573092857644974193Apple-tab-span" style="white-space:pre-wrap">        </span><span class="gmail-m_6573092857644974193Apple-tab-span" style="white-space:pre-wrap">        </span><br><span class="gmail-"><br>Example 4 :<br>-                dictionary.<wbr>first { (column, value) in column.lowercased() == orderedColumn.lowercased() }<br></span>+                dictionary.first { ((column, value)) in column.lowercased() == orderedColumn.lowercased() }<br></div><div><br></div><div><br></div><div>What do you think?  Seems like it would solve the type checker problem, uglify the code a lot less, and make the fixit/migration happily trivial.</div><div><br></div></div></blockquote><div><br></div><div>+1.</div><div><br></div><div>Migration path would be a little less simple if the parameter clause has type annotations:</div><div><br></div><div><div><font face="monospace, monospace">-    let fn: Int = { (v: String, k: Int) in</font></div><div><font face="monospace, monospace">+    let fn: Int = { ((v, k): (String, Int)) in</font></div><div><br></div><div>Also, if we accept patterns for closure parameters, we probably don&#39;t want to accept &#39;...&#39; for them.</div></div><div><br></div><div><span style="font-family:monospace,monospace">let fn = { ((_, v): (Int, String)...) -&gt; Int in</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div></div><div>-Chris</div><div><br></div><div><br></div><div><br></div></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></div>