Regarding the requiring of parentheses for arguments in closures: I'd suggest to look into SE-0066's paragraph "Should we require parentheses in closure expression parameter lists?" and "Rationale" for this SE: https://lists.swift.org/pipermail/swift-evolution-announce/2016-May/000138.html (SE-0066: https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md)

Personally I agree that closures worth their own syntax and that it is important to keep closure's syntax lightweight. So, IMO we should keep {x, y in ..} syntax for closures and this should be jut equivalent for {(x, y) in ..}, i.e. one can use first or second depending on his/her style.

I think the idea of double parentheses for tuple argument destructing in closure is the best solution as it has a relationship to introduced by SE-0066 type of function with tuple argument. I.e. :

func foo(_ x: (Int, Int)) {..}

type(of: foo) // should be ((Int, Int)) -> ()
// note: not  (Int, Int) -> ()

var g : ((Int, Int))->() = f

g = {((x1, x2)) in ... } // feels like correct syntax for type ((Int, Int))->()
g = {pair in ... } // also OK, single tuple argument

g = {(x1, x2) in ...} // should be ERROR: incompatible type of closure

But during the discussion of SE-0110 there was some negative reaction for this 
idea.

Btw, while we are discussing SE-0110 and SE-0066, I'd like to point to another change that can IMO have impact for functional programming, so I believe it is better to discuss this also.
Currently(Swift 3.1) we are allowed to have this:

var f : ()->() = {x in print(x)}
f() // ()
f = {_ in print(x)}

I.e. you can now assign a closure with single argument as function type that has 0 parameters(because of implicit Void argument).

Also, after SE-0066 and 0110 implemented, passing Void to function declared without parameters should not be allowed, so for example you can't call f(print("sdfsdf")) i.e. can't pass result of Void to some other function that is declared without parameters.

Small naive example:

func schedule<T>(with: T, do: (T) -> Void) {...}

//--- can't change this function for some reason ---
func foo() { .. } // just do something
//---

current code:

schedule(with: (), do: foo)

new code:

schedule(with: (), do: {_ in foo()})

Actually I believe this is a good change, but should be taken into 
consideration.

Vladimir.

On 26.05.2017 22:35, Robert Bennett via swift-evolution wrote:
On the contrary I think the solution can absolutely be to break other code. Allowing no parentheses is not a very useful shorthand -- it only saves two characters -- and with SE-0110 actually obscures the logic. Always requiring parentheses makes it clear that "{ (arg) in ..." can be replaced with "{ ((key, value)) in ..." when arg is a 2-tuple; the outer parentheses denote an argument list, and anything inside them is the argument, consistent with other parts of the language. Allowing "{ arg in ..." but not "{ (key, value) in ..." is sure to leave some people scratching their heads because"{ arg in ..." suggests that it is arguments that are passed to closures (as is the case with functions) and not tuples. The correctness of "{ arg in ..." relies too heavily on the equivalence between a 1-tuple and a single element, an equivalence that does not hold for higher arities.

I'm not *too* strongly wed to this, though. I care much more strongly about allowing "{ ((key, value)) in ..." than prohibiting "{ arg in ...". I only brought up the latter to try to improve the consistency of the language and to make clear that "{ ((key, value)) in ..." is the correct way of achieving the old style "{ (key, value) in ..."

On May 26, 2017, at 2:57 PM, Xiaodi Wu <xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>> wrote:

Requiring parentheses in closures like that was discussed during SE-0110 and rejected; the rationale was that it's a useful shorthand, and that the whole closure syntax is wildly different from function declarations: you don't need to write the type of the arguments, and you don't need to write the return value, so why would it make sense to enforce this particular formality?

At this point, I'd be very much against now requiring it. The whole rationale for revisiting SE-0110 is that it is breaking lots of code, and the solution cannot be to break lots of other code. The double parenthesis syntax or the let syntax for destructuring seem to be fine mitigations, the former because it strictly parallels the change in syntax in SE-0110 where a single tuple argument has two sets of parentheses, and the latter because it's the same destructuring syntax as is used elsewhere for pattern matching. On Fri, May 26, 2017 at 11:45 David Sweeris via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:


    > On May 26, 2017, at 08:14, Robert Bennett via swift-evolution
    <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
    >
    > Alternatively, for maximum consistency we could make "{ arg in ..." 
illegal
    as well, requiring parentheses around "arg". This would mirror the 
parentheses
    necessary in e.g., "let f: (Int) -> Int", and there would be no confusion 
as to
    why " { arg in ..." is legal but not "{ (key, value) in ...".

    I think I would support that. Until quite recently, I was under the 
impression
    that closures' "inner signatures" were part of that proposal, anyway.

    (Come to think of it... were they? I suppose it could be a bug that the 
"old"
    syntax is still accepted here.)

    - Dave Sweeris
    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    https://lists.swift.org/mailman/listinfo/swift-evolution



_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to