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