<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 Jun 1, 2017, at 3:06 PM, John McCall via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 1, 2017, at 2:39 PM, Pavol Vaskovic <<a href="mailto:pali@pali.sk" class="">pali@pali.sk</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><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" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br class="">
I understand that there are developers who dislike SE-0110'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 class=""><br class=""></div><div class="">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 class="">* concise but obfuscate code ($0.1, ...)</div><div class="">* 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 class=""><br class=""></div><div class="">Maybe I misunderstood you, but I don't think this is marginal issue affecting only some "developers that dislike the impact on certain kinds of functional programming". </div></div></div></div></div></blockquote><div class=""><br class=""></div>You'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 class=""></div><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><div><br class=""></div><div>Example 1<br class="">- return columns.index { (column, _) in column.lowercased() == lowercaseName }<br class="">+ return columns.index { $0.0.lowercased() == lowercaseName }<br class=""><br class="">Example 2 :<br class="">- .map { (mappedColumn, baseColumn) -> (Int, String) in<br class="">+ .map { (pair) -> (Int, String) in<br class="">+ let mappedColumn = pair.key<br class="">+ let baseColumn = pair.value<br class=""><br class="">Example 3 :<br class="">- .map { (table, columns) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class="">+ .map { "\($0.key)(\($0.value.sorted().joined(separator: ", ")))" }<br class=""><br class="">Example 4 :<br class="">- dictionary.first { (column, value) in column.lowercased() == orderedColumn.lowercased() }<br class="">+ dictionary.first { $0.key.lowercased() == orderedColumn.lowercased() }<br class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div class="">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's to:</div><div class=""><br class=""></div><div class="">Example 1<br class="">- return columns.index { (column, _) in column.lowercased() == lowercaseName }<br class="">+ return columns.index { ((column, _)) in column.lowercased() == lowercaseName }<br class=""><br class="">Example 2 :<br class="">- .map { (mappedColumn, baseColumn) -> (Int, String) in<br class="">+ .map { ((mappedColumn, baseColumn)) -> (Int, String) in<br class=""><br class="">Example 3 :<br class="">- .map { (table, columns) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class="">+ .map { ((table, columns)) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><br class="">Example 4 :<br class="">- dictionary.first { (column, value) in column.lowercased() == orderedColumn.lowercased() }<br class="">+ dictionary.first { ((column, value)) in column.lowercased() == orderedColumn.lowercased() }<br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>