[swift-evolution] Revisiting SE-0110

Vladimir.S svabox at gmail.com
Thu Jun 1 05:25:25 CDT 2017


On 01.06.2017 0:42, John McCall wrote:
>> On May 31, 2017, at 2:02 PM, Stephen Celis <stephen.celis at gmail.com> wrote:
>>> On May 28, 2017, at 7:04 PM, John McCall via swift-evolution
>>> <swift-evolution at swift.org> wrote:
>>> 
>>> Yes, I agree.  We need to add back tuple destructuring in closure parameter
>>> lists because this is a serious usability regression.  If we're reluctant to
>>> just "do the right thing" to handle the ambiguity of (a,b), we should at least
>>> allow it via unambiguous syntax like ((a,b)).  I do think that we should just
>>> "do the right thing", however, with my biggest concern being whether there's
>>> any reasonable way to achieve that in 4.0.
>> 
>> Closure parameter lists are unfortunately only half of the equation here. This
>> change also regresses the usability of point-free expression.
> 
> The consequences for point-free style were expected and cannot really be
> eliminated without substantially weakening SE-0110.  Closure convenience seems to
> me to be a much more serious regression.

John, do you also want to say "and without weakening SE-0066"? Because, if I 
understand correctly, in this case:

  func add(_ x: Int, _ y: Int) -> Int {
     return x + y
   }

   zip([1, 2, 3], [4, 5, 6]).map(add)

.. we have a clear function type mismatch situation, when map() expects function of 
type ((Int, Int))->Int, but function of type (Int,Int)->Int is provided ? So probably 
the additional 'reason' of the 'problem' in this case is SE-0066, no?
Or I don't understand the SE-0066 correctly..
Do we want to allow implicit conversions between function type ((Int,Int))->Int and 
(Int,Int)->Int?

Quote from SE-0066:
---
(Int, Int) -> Int    // function from Int and Int to Int
((Int, Int)) -> Int  // function from tuple (Int, Int) to Int
---

During this discussion I see a wish of some group of developers to just return back 
tuple splatting for function/closure arguments, so they can freely send tuple to 
function/closure accepting a list of parameters(and probably vise-versa).
Is it worth to follow SE-0066 and SE-0110 as is, i.e. disallow tuple deconstructing 
and then, as additive change improve the situation with tuple 
splatting/deconstructing later with separate big proposal?

Btw, about the SE-0110 proposal. It was discussed, formally reviewed and accepted. I 
expect that its revision also should be formally proposed/reviewed/accepted to 
collect a wide range of opinions and thoughts, and attract the attention of 
developers in this list to the subject.


Also, if we revisit SE-0110, will this code be allowed?:

func foo(_ callback: ((Int,Int))->Void) {}
let mycallback = {(x:Int, y:Int)->Void in }
foo(mycallback)

and

func foo(_ callback: (Int,Int)->Void) {}
let mycallback = {(x: (Int, Int))->Void in }
foo(mycallback)

If so, what will be result of this for both cases? :

print(type(of:mycallback)) // (Int,Int)->Void or ((Int,Int))->Void

If allowed, do we want to allow implicit conversion between types (Int,Int)->Void and 
((Int,Int))->Void in both directions?  (Hello tuple splatting?)

> 
> John.
> 
> 
>> 
>> func add(_ x: Int, _ y: Int) -> Int { return x + y }
>> 
>> zip([1, 2, 3], [4, 5, 6]).map(add)
>> 
>> // error: nested tuple parameter '(Int, Int)' of function '(((_.Element,
>> _.Element)) throws -> _) throws -> [_]' does not support destructuring
>> 
>> This may not be a common pattern in most projects, but we heavily use this style
>> in the Kickstarter app in our functional and FRP code. Definitely not the most
>> common coding pattern, but a very expressive one that we rely on.
>> 
>> Our interim solution is a bunch of overloaded helpers, e.g.:
>> 
>> func tupleUp<A, B, C>(_ f: (A, B) -> C) -> ((A, B)) -> C { return }
>> 
>> zip([1, 2, 3], [4, 5, 6]).map(tupleUp(add))
>> 
>> Stephen
> 
> .
> 


More information about the swift-evolution mailing list