[swift-evolution] Revisiting SE-0110
Vladimir.S
svabox at gmail.com
Mon Jun 5 11:20:45 CDT 2017
Yes, double parenthesis for tuple argument destructuring in closure was discussed in
this thread, and I feel it is one of the best options.
But the main question I can't find the clear answer for, what will be with
function/closure types in Swift 4. IMO *this* is the main question, not the syntax
for tuple destructuring.
Chris, could you please help to clarify the situation with SE-0066 and SE-0110?
In Rationale part of the SE-0110 acceptance message you said:
"... The community and core team agree that this proposal is the right thing to do,
and many agree that this could probably have been treated as a bug fix on a previous
proposal.
..."
(https://lists.swift.org/pipermail/swift-evolution-announce/2016-July/000215.html)
Were you thinking about SE-0110 just as bug fix for SE-0066/SE-0029?
What is your opinion, can we revisit SE-0110 without revisiting SE-0066?
I mean that for me SE-0066 clearly separated *types* for function with one tuple
argument and a list of arguments, so (Int,Int)->Void is not the same *type* as
((Int,Int))->Void, and so we just must to assign a right concrete type for
closure(depending on its arguments), so we must separate closures that takes one
tuple argument and a list of arguments. And SE-0110 just clarifies this.
How do you think, what should be a *type* of these constants after SE-0066?:
let closure1 = {(x: Int, y: Int) in}
let closure2 = {(x: (Int,Int)) in }
print(type(of: closure1)) // ?
print(type(of: closure2)) // ?
For me, based on *SE-0066*, they must be typed as (Int, Int)->Void and
((Int,Int))->Void accordingly, no?
Should type(of: closure1) == type(of: closure2) ?
Can (closure2 is (Int,Int)->Void) == true ?
and (closure1 is ((Int,Int))->Void) == true ?
Having function
func foo(callback: (_ x:(Int,Int))->Void) {..}
, should we be able to just send closure1 to it? I.e.
foo(callback: closure1) // ?
foo(callback: {(x: Int, y: Int) in}) // and here?
foo(callback: {x, y in }) // and here?
I even think that we can have implicit conversion between these *types* of
closures/funcs (one tuple vs arg list), because this seems to be very handy and used
a lot, but IMO after SE-0066 we should have clear and strict type for each kind of
func/closure and then, can have clear rule that we can use one *type*, where *another
type* is required.
Or allow just tuple destructuring by *special* syntax in closure. Again, closure will
be of correct *type* but contains tuple destructuring syntax.
Or disallow using of different *type* of func/closure when another type is
requested.(Exactly this was proposed and accepted by SE-0110, that was inspired by
SE-0066)
Having all these said, I can't understand how we can actually revisit SE-0110,
because it just clarifies for closures what SE-0066 requires for function types.
Thank you.
Vladimir.
On 04.06.2017 20:16, Chris Lattner via swift-evolution wrote:
>
>> On Jun 1, 2017, at 3:06 PM, John McCall via swift-evolution
>> <swift-evolution at swift.org <mailto: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
>
>
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
More information about the swift-evolution
mailing list