[swift-evolution] [pitch] Eliminate the "T1 -> T2" syntax, require "(T1) -> T2"

Vladimir.S svabox at gmail.com
Wed Apr 20 02:02:04 CDT 2016


Great points! We definitely have some mess with tuples&parameters list in 
current Swift. Especially after we removed tuple splat feature.

But right now can't see what we can do about this.

(T1,T2) -> (T3,T4) really reads as "tuple (T1,T2) to tuple (T3,T4)" and 
this is partially true as result is really tuple (T3,T4).
Correct form looks like T1,T2 -> (T3,T4), but this just can't be expressed 
in current syntax of Swift - we need parens for param names, their 
modifiers like inout/@noescape etc., don't think Swift can parse without 
parens.



Even more. This is ok in current Swift 3:

let f : ((Int, Int)) -> (Int, Int) = { return ($0, $1) }
let f2 : ((Int, Int)) -> (Int, Int) = { return ($0.0, $0.1) }

I.e. absolutely the same functions, declared in different way. Why it 
allows to point a tuple to $0 & $1, instead of just $0.0 $0.1 ?


On 19.04.2016 21:24, David Owens II via swift-evolution wrote:
> I have a different read of the proposal I guess... I actually find that this:
>
>     (Int, Int) -> (Int, Int)
>
>
> Naturally reads take a single pair (e.g. tuple) of (Int, Int) and return a
> single pair of (Int, Int)
>
> This actually looks and feels like the right implementation to me:
>
>     let tx: (Int, Int) -> (Int, Int) = { ($0.1, $0.0) }
>
>
> And I am saying that this would be explicitly wrong:
>
>     let tx: (Int, Int) -> (Int, Int) = { ($1, $0) }
>
>
> If I wanted a type signature of that took two Int params, I would expect to
> write this:
>
>     let tx: Int, Int -> (Int, Int) = { ($1, $0) }
>
>
> That reads, a type signature that takes two Int values and returns a single
> (Int, Int) pair.
>
> The problem, to me at least, is that the function declaration overloads the
> meaning of () as "start of parameter list for function declaration".
>
>     func tx((Int, Int)) -> (Int, Int) { return ($0.1, $0.0) }
>
>
> So now you have this mess to say the same thing: take a single pair of Int
> and return a pair of Int.
>
> Similarly, if the () are going to required for parameter lists in function
> declarations, I really struggle to see why these two forms should mean the
> same thing:
>
>     y = x.sorted { (lhs, rhs) in rhs < lhs }
>     y = x.sorted { lhs, rhs in rhs < lhs }
>
>
> Dropping the type signatures because that can be inferred is one thing, but
> changing the structure of the parameter list seems like an orthogonal
> optimization.
>
>     y = x.sorted { (lhs : Int, rhs : Int) -> Bool in rhs < lhs }
>     y = x.sorted { (lhs, rhs) in rhs < lhs }
>     { $1 < $0 }
>
>
> This process keeps the structural elements while dropping all of the type
> pieces and maintains the consistency that in function types (regardless of
> how they are defined), the () denotes a parameter list. If you actually
> want a tuple within the parameter list, you need to do `((lhs, rhs))`.
>
> -David
>
>> On Apr 19, 2016, at 9:24 AM, Erica Sadun via swift-evolution
>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>>
>>> On Apr 19, 2016, at 9:44 AM, David Rönnqvist <david.ronnqvist at gmail.com
>>> <mailto:david.ronnqvist at gmail.com>> wrote:
>>>
>>> Would this also affect the syntax for naming closure arguments? For
>>> example, would this (taken from "The Swift Programming Language (Swift
>>> 2.2)”):
>>>
>>>  1. |reversed = names.sort( { s1, s2 in return s1 > s2 } )|
>>>
>>> have to be written like this:
>>>
>>>  1. |reversed = names.sort( { (s1, s2) in return s1 > s2 } )|
>>>
>>> or is that a different syntax?
>>>
>>> As a developer focused on _writing_ and _reading_ code like this, I
>>> don’t see the real benefits of this change. It only feels natural to me
>>> that I would be able to omit the parentheses when there is only one
>>> type, but that I would need them to group multiple arguments or to label
>>> arguments.
>>>
>>> That said, I don’t feel strongly about it and the work of transitioning
>>> our code would be minimal. If this change provides other engineering
>>> benefits that aren’t noticeable on the surface, then I’m positive to the
>>> change for those reasons.
>>>
>>> - David
>>
>> It would not affect the closure syntax. To paraphrase Chris:
>>
>> No. Swift’s syntactic shortcuts in its closure parameter lists benefit
>> simple functional algorithms. Few people would choose to write fully
>> specified long-form declarations when, for example, reverse-sorting an
>> array of integers:
>>
>> |y = x.sorted { (lhs : Int, rhs : Int) -> Bool in rhs < lhs }|
>>
>> Compare the long form with this simpler form:
>>
>> |y = x.sorted { lhs, rhs in rhs < lhs }|
>>
>> You can use the even shorter form of |{ $1 < $0 }|.
>>
>> Closures offer a structurally distinct class of syntactic sugar:
>>
>>   * You may elide parentheses (even with multiple arguments)
>>   * You may omit the return type
>>   * You may omit types
>>   * You may omit the parameter list in its entirety
>>
>> Short of a complete rethink of closure syntax, requiring parentheses
>> there would not improve the language in any measurable way.
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> 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