[swift-evolution] Revisiting SE-0110

Chris Lattner clattner at nondot.org
Sun Jun 4 12:16:21 CDT 2017


> On Jun 1, 2017, at 3:06 PM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On Jun 1, 2017, at 2:39 PM, Pavol Vaskovic <pali at pali.sk <mailto:pali at pali.sk>> wrote:
>> 
>> On Thu, Jun 1, 2017 at 8:52 PM, John McCall via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> 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. 
>> 
>> 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:
>> * concise but obfuscate code ($0.1, ...)
>> * 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)
>> 
>> 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". 
> 
> 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.

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):

Example 1
-        return columns.index { (column, _) in column.lowercased() == lowercaseName }
+        return columns.index { $0.0.lowercased() == lowercaseName }

Example 2 :
-            .map { (mappedColumn, baseColumn) -> (Int, String) in
+            .map { (pair) -> (Int, String) in
+                let mappedColumn = pair.key
+                let baseColumn = pair.value

Example 3 :
-                .map { (table, columns) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }		
+                .map { "\($0.key)(\($0.value.sorted().joined(separator: ", ")))" }

Example 4 :
-                dictionary.first { (column, value) in column.lowercased() == orderedColumn.lowercased() }
+                dictionary.first { $0.key.lowercased() == orderedColumn.lowercased() }




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:

Example 1
-        return columns.index { (column, _) in column.lowercased() == lowercaseName }
+       return columns.index { ((column, _)) in column.lowercased() == lowercaseName }

Example 2 :
-            .map { (mappedColumn, baseColumn) -> (Int, String) in
+            .map { ((mappedColumn, baseColumn)) -> (Int, String) in

Example 3 :
-                .map { (table, columns) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }		
+                .map { ((table, columns)) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }		

Example 4 :
-                dictionary.first { (column, value) in column.lowercased() == orderedColumn.lowercased() }
+                dictionary.first { ((column, value)) in column.lowercased() == orderedColumn.lowercased() }


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.

-Chris



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170604/2d930276/attachment.html>


More information about the swift-evolution mailing list