Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-12 Thread Jérémie Girault via swift-evolution
I think it’s interesting to discuss tuples, especially around 1-sized
tuples.
I also have an issue about 0-sized tuples and drafted a proposal here.

https://github.com/jeremiegirault/swift-evolution/blob/master/proposals/-flatten-void.md

I think by addressing empty, 1 and n-sized tuples issues we can avoid the
regressions of the language and greatly improve swift4

> > Le 9 juin 2017 à 10:07, Mark Laceymailto:mark.la...@apple.com'>
mailto:mark.la...@apple.com )>a écrit :
> >
> > I’m not trying to argue that it’s impossible to do. I don’t think it’s
a good idea at all. That’s subjective. Me saying “that really should be an
error” is a subjective statement. I don’t have to say “This is a subjective
statement” to make a subjective statement.
> Yes, sorry: It's so easy to sound assertive even when we just want to
share and communicate opinions.
>
> > > I *do* suggest a specific handling of { _ ... }. I have shown how it
can be implemented in a non-ambiguous fashion.
> >
> > Your own comment says this should be considered ambiguous. It’s
unambiguous now. What I am asking is how is that an improvement?
> I suggest { _ in ... } is ambiguous only in case of function overloading.
In this case, you have { (_) in ... } and { (_,_) in ... } for
disambiguation:
>
> funcoverloaded(_closure: (Int,Int) ->Int) ->String{return"overloaded 1"}
> funcoverloaded(_closure: ((lhs:Int, rhs:Int)) ->Int)
->String{return"overloaded 2"}
>
>
>
>
> overloaded {_in1}// error: ambiguous use of ‘overloaded'
>
>
>
>
>
> overloaded { (_)in1}// "overloaded 1”
>
>
>
>
>
>
>
>
>
>
> overloaded { (_, _)in1}// "overloaded 2”
>
>
>
>
>
>
>
>
>
>
>
> When a function is not overloaded, then { _ in ... } would always mean "I
don't care", and is always accepted except for closures that take no
argument at all:
>
> funcf1(_closure: () ->Int) ->String{return"f1"}
> funcf2(_closure: (Int) ->Int) ->String{return"f2"}
> funcf3(_closure: (Int,Int) ->Int) ->String{return"f3"}
> funcf4(_closure: ((lhs:Int, rhs:Int)) ->Int) ->String{return"f4"}
>
> f1 {_in1}// error
>
> f2 {_in1}//OK, you don't care
>
> f3 {_in1}// OK, you don't care
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> f3 {(_,_)in1}// OK, just what I expected!
>
> f4 {_in1}// OK, you don't care
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> f4 {(_)in1}// OK,just what I expected!
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> f4 {(_,_)in1}// OK, maybe you use tuple splatting somewhere else and want
to be consistent
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> All this is *possible*. And I don't see how it breaks anything. On the
other side, it eases everyday life, reduces clutter, and avoids useless
punctuation.
> Gwendal
>
>
>
>

—
very short reply expected - vsre.info
Jérémie Girault
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Gwendal Roué via swift-evolution
> Le 9 juin 2017 à 10:07, Mark Lacey  a écrit :
> 
> I’m not trying to argue that it’s impossible to do. I don’t think it’s a good 
> idea at all. That’s subjective. Me saying “that really should be an error” is 
> a subjective statement. I don’t have to say “This is a subjective statement” 
> to make a subjective statement.

Yes, sorry: It's so easy to sound assertive even when we just want to share and 
communicate opinions.

>> I *do* suggest a specific handling of { _ ... }. I have shown how it can be 
>> implemented in a non-ambiguous fashion. 
> 
> Your own comment says this should be considered ambiguous. It’s unambiguous 
> now. What I am asking is how is that an improvement?

I suggest { _ in ... } is ambiguous only in case of function overloading. In 
this case, you have { (_) in ... } and { (_,_) in ... } for disambiguation:

func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
"overloaded 1" }
func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
return "overloaded 2" }
overloaded { _ in 1 }  // error: ambiguous use of ‘overloaded'
overloaded { (_) in 1 }// "overloaded 1”
overloaded { (_, _) in 1 } // "overloaded 2”

When a function is not overloaded, then { _ in ... } would always mean "I don't 
care", and is always accepted except for closures that take no argument at all:

func f1(_ closure: () -> Int) -> String { return "f1" }
func f2(_ closure: (Int) -> Int) -> String { return "f2" }
func f3(_ closure: (Int, Int) -> Int) -> String { return "f3" }
func f4(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { return "f4" }

f1 { _ in 1 }  // error

f2 { _ in 1 }  // OK, you don't care

f3 { _ in 1 }  // OK, you don't care
f3 { (_, _) in 1 } // OK, just what I expected!

f4 { _ in 1 }  // OK, you don't care
f4 { (_) in 1 }// OK, just what I expected!
f4 { (_, _) in 1 } // OK, maybe you use tuple splatting somewhere else and 
want to be consistent

All this is *possible*. And I don't see how it breaks anything. On the other 
side, it eases everyday life, reduces clutter, and avoids useless punctuation.
Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Mark Lacey via swift-evolution

> On Jun 9, 2017, at 12:55 AM, Gwendal Roué  wrote:
> 
>> 
>> Le 9 juin 2017 à 09:41, Mark Lacey > > a écrit :
>> 
>> 
>>> On Jun 9, 2017, at 12:12 AM, Gwendal Roué >> > wrote:
>>> 
> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
> "notOverloaded1" }
> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> 
> String { return "notOverloaded3" }
> 
> func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
> "overloaded 1" }
> func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
> return "overloaded 2" }
> 
> // not overloaded => not ambiguous
> notOverloaded1 { x, y in x + y }
> notOverloaded1 { (x, y) in x + y }
> notOverloaded1 { _ in 1 }
> notOverloaded2 { x, y in x + y }
> notOverloaded2 { (x, y) in x + y }
> notOverloaded2 { _ in 1 }
> 
> // overloaded => resolve ambiguity on closure argument, when possible
> overloaded { x, y in x + y }// "overloaded 1"
> overloaded { (x, y) in x + y }  // "overloaded 1"
> overloaded { t in t.lhs + t.rhs }   // "overloaded 2"
> overloaded { (t) in t.lhs + t.rhs } // "overloaded 2”
 
 This is exactly what happens today as a result of SE-0110 since the first 
 two calls take two arguments, and the next two take a single argument.
>>> 
>>> No, as a playground quickly reveals:
>> 
>> I was specifically referring to the last four statements but could have made 
>> that more clear.
>> 
>>> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
>>> "notOverloaded1" }
>>> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String 
>>> { return "notOverloaded3" }
>>> 
>>> // not overloaded => not ambiguous
>>> notOverloaded1 { x, y in x + y }
>>> notOverloaded1 { (x, y) in x + y }
>>> notOverloaded1 { _ in 1 }  // Swift 4 error
>> 
>> This really should be an error.
> 
> I argue this is a subjective statement, and my own subjective statement is 
> that it should not to be an error. So that { _ in ... } would always mean "I 
> don't care".
> 
>> It’s one thing to say that { x, y in } should work as it used to in the case 
>> where a closure taking a tuple is expected, but something else entirely to 
>> say that _ should work in any case, regardless of whether a closure taking N 
>> arguments or a closure taking an N-tuple is expected for any N. I can see a 
>> desire to make _ work for any tuple, and _, _ work for a two-tuple based on 
>> context if e.g. “x, y in” also works, but not for _ working where a closure 
>> requiring N independent arguments is expected.
> 
> Yes. That's why it's subjective. You argue that you don't like it, not that 
> it's impossible to do. Because you can't prove it's impossible to do.

I’m not trying to argue that it’s impossible to do. I don’t think it’s a good 
idea at all. That’s subjective. Me saying “that really should be an error” is a 
subjective statement. I don’t have to say “This is a subjective statement” to 
make a subjective statement.

> Because I have shown that it is.
> In a nice manner that is easy to developers.
> 
>> 
>>> notOverloaded2 { x, y in x + y }   // Swift 4 error
>>> notOverloaded2 { (x, y) in x + y } // Swift 4 error
>> 
>> In these cases using the tuple labels works as well (as it does in your 
>> examples where the overloaded function is involved). I’m not arguing that 
>> it’s as good as being able to do the apparent destructuring, but just want 
>> to point out that it works. I didn’t get the sense from your email that you 
>> found that objectionable in the cases involving overloads, but perhaps you 
>> do.
>> 
>>> notOverloaded2 { _ in 1 }
>>> 
>>> Those errors are the famous regressions we want to fix.
>>> 
> overloaded { _ in 1 }   // error: ambiguous use of 
> ‘overloaded'
 
 With SE-0110 in its current form, this calls the tuple version since there 
 is a single closure parameter listed.
>>> 
>>> It would be nicer if. { _ in ... } would always mean "I don't care". With 
>>> an ambiguity in the sample code we're looking at, and a compiler error.
>> 
>> How does making something that is unambiguous today actually be ambiguous 
>> improve things?
> 
> I *do* suggest a specific handling of { _ ... }. I have shown how it can be 
> implemented in a non-ambiguous fashion.

Your own comment says this should be considered ambiguous. It’s unambiguous 
now. What I am asking is how is that an improvement?

Mark

> Please don't act as if I did not.

> 
> Now the specific case of { _ ... } is interesting, but I wouldn't make it as 
> important as the other regressions.
> 
> I should make an exhaustive compilation of Swift 4 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Gwendal Roué via swift-evolution

> Le 9 juin 2017 à 09:41, Mark Lacey  a écrit :
> 
> 
>> On Jun 9, 2017, at 12:12 AM, Gwendal Roué > > wrote:
>> 
 func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
 "notOverloaded1" }
 func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> 
 String { return "notOverloaded3" }
 
 func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
 "overloaded 1" }
 func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
 return "overloaded 2" }
 
 // not overloaded => not ambiguous
 notOverloaded1 { x, y in x + y }
 notOverloaded1 { (x, y) in x + y }
 notOverloaded1 { _ in 1 }
 notOverloaded2 { x, y in x + y }
 notOverloaded2 { (x, y) in x + y }
 notOverloaded2 { _ in 1 }
 
 // overloaded => resolve ambiguity on closure argument, when possible
 overloaded { x, y in x + y }// "overloaded 1"
 overloaded { (x, y) in x + y }  // "overloaded 1"
 overloaded { t in t.lhs + t.rhs }   // "overloaded 2"
 overloaded { (t) in t.lhs + t.rhs } // "overloaded 2”
>>> 
>>> This is exactly what happens today as a result of SE-0110 since the first 
>>> two calls take two arguments, and the next two take a single argument.
>> 
>> No, as a playground quickly reveals:
> 
> I was specifically referring to the last four statements but could have made 
> that more clear.
> 
>> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
>> "notOverloaded1" }
>> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String 
>> { return "notOverloaded3" }
>> 
>> // not overloaded => not ambiguous
>> notOverloaded1 { x, y in x + y }
>> notOverloaded1 { (x, y) in x + y }
>> notOverloaded1 { _ in 1 }  // Swift 4 error
> 
> This really should be an error.

I argue this is a subjective statement, and my own subjective statement is that 
it should not to be an error. So that { _ in ... } would always mean "I don't 
care".

> It’s one thing to say that { x, y in } should work as it used to in the case 
> where a closure taking a tuple is expected, but something else entirely to 
> say that _ should work in any case, regardless of whether a closure taking N 
> arguments or a closure taking an N-tuple is expected for any N. I can see a 
> desire to make _ work for any tuple, and _, _ work for a two-tuple based on 
> context if e.g. “x, y in” also works, but not for _ working where a closure 
> requiring N independent arguments is expected.

Yes. That's why it's subjective. You argue that you don't like it, not that 
it's impossible to do. Because you can't prove it's impossible to do. Because I 
have shown that it is. In a nice manner that is easy to developers.

> 
>> notOverloaded2 { x, y in x + y }   // Swift 4 error
>> notOverloaded2 { (x, y) in x + y } // Swift 4 error
> 
> In these cases using the tuple labels works as well (as it does in your 
> examples where the overloaded function is involved). I’m not arguing that 
> it’s as good as being able to do the apparent destructuring, but just want to 
> point out that it works. I didn’t get the sense from your email that you 
> found that objectionable in the cases involving overloads, but perhaps you do.
> 
>> notOverloaded2 { _ in 1 }
>> 
>> Those errors are the famous regressions we want to fix.
>> 
 overloaded { _ in 1 }   // error: ambiguous use of 
 ‘overloaded'
>>> 
>>> With SE-0110 in its current form, this calls the tuple version since there 
>>> is a single closure parameter listed.
>> 
>> It would be nicer if. { _ in ... } would always mean "I don't care". With an 
>> ambiguity in the sample code we're looking at, and a compiler error.
> 
> How does making something that is unambiguous today actually be ambiguous 
> improve things?

I *do* suggest a specific handling of { _ ... }. I have shown how it can be 
implemented in a non-ambiguous fashion. Please don't act as if I did not.

Now the specific case of { _ ... } is interesting, but I wouldn't make it as 
important as the other regressions.

I should make an exhaustive compilation of Swift 4 regressions, so that you 
opponents can see how *far* things have changed, fixing a few corner cases, and 
breaking tons of valid code. At least we could discuss each case in isolation.

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Mark Lacey via swift-evolution

> On Jun 9, 2017, at 12:12 AM, Gwendal Roué  wrote:
> 
>>> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
>>> "notOverloaded1" }
>>> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String 
>>> { return "notOverloaded3" }
>>> 
>>> func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
>>> "overloaded 1" }
>>> func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
>>> return "overloaded 2" }
>>> 
>>> // not overloaded => not ambiguous
>>> notOverloaded1 { x, y in x + y }
>>> notOverloaded1 { (x, y) in x + y }
>>> notOverloaded1 { _ in 1 }
>>> notOverloaded2 { x, y in x + y }
>>> notOverloaded2 { (x, y) in x + y }
>>> notOverloaded2 { _ in 1 }
>>> 
>>> // overloaded => resolve ambiguity on closure argument, when possible
>>> overloaded { x, y in x + y }// "overloaded 1"
>>> overloaded { (x, y) in x + y }  // "overloaded 1"
>>> overloaded { t in t.lhs + t.rhs }   // "overloaded 2"
>>> overloaded { (t) in t.lhs + t.rhs } // "overloaded 2”
>> 
>> This is exactly what happens today as a result of SE-0110 since the first 
>> two calls take two arguments, and the next two take a single argument.
> 
> No, as a playground quickly reveals:

I was specifically referring to the last four statements but could have made 
that more clear.

> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
> "notOverloaded1" }
> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
> return "notOverloaded3" }
> 
> // not overloaded => not ambiguous
> notOverloaded1 { x, y in x + y }
> notOverloaded1 { (x, y) in x + y }
> notOverloaded1 { _ in 1 }  // Swift 4 error

This really should be an error. It’s one thing to say that { x, y in } should 
work as it used to in the case where a closure taking a tuple is expected, but 
something else entirely to say that _ should work in any case, regardless of 
whether a closure taking N arguments or a closure taking an N-tuple is expected 
for any N. I can see a desire to make _ work for any tuple, and _, _ work for a 
two-tuple based on context if e.g. “x, y in” also works, but not for _ working 
where a closure requiring N independent arguments is expected.

> notOverloaded2 { x, y in x + y }   // Swift 4 error
> notOverloaded2 { (x, y) in x + y } // Swift 4 error

In these cases using the tuple labels works as well (as it does in your 
examples where the overloaded function is involved). I’m not arguing that it’s 
as good as being able to do the apparent destructuring, but just want to point 
out that it works. I didn’t get the sense from your email that you found that 
objectionable in the cases involving overloads, but perhaps you do.

> notOverloaded2 { _ in 1 }
> 
> Those errors are the famous regressions we want to fix.
> 
>>> overloaded { _ in 1 }   // error: ambiguous use of 
>>> ‘overloaded'
>> 
>> With SE-0110 in its current form, this calls the tuple version since there 
>> is a single closure parameter listed.
> 
> It would be nicer if. { _ in ... } would always mean "I don't care". With an 
> ambiguity in the sample code we're looking at, and a compiler error.

How does making something that is unambiguous today actually be ambiguous 
improve things?

Mark

> The { (_, _) in ... } form is arguably cluttered, and it would be nicer it is 
> was required only for disambiguition.
> 
>>> overloaded { (_) in 1 } // "overloaded 1”
>> 
>> With SE-0110 in its current form, this calls the tuple version since there 
>> is a single closure parameter listed. I don’t understand why you would 
>> suggest this should call the two-argument version since that’s inconsistent 
>> with the other closures above that have a single argument.
>> 
>>> overloaded { (_, _) in 1 }  // "overloaded 2”
>> 
>> With SE-0110 in its current form, this calls the two-argument version since 
>> there are two listed arguments.
> 
> I was wrong, sorry. I meant what you replied.
> 
> Gwendal
> 

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Gwendal Roué via swift-evolution
>> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
>> "notOverloaded1" }
>> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String 
>> { return "notOverloaded3" }
>> 
>> func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
>> "overloaded 1" }
>> func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
>> return "overloaded 2" }
>> 
>> // not overloaded => not ambiguous
>> notOverloaded1 { x, y in x + y }
>> notOverloaded1 { (x, y) in x + y }
>> notOverloaded1 { _ in 1 }
>> notOverloaded2 { x, y in x + y }
>> notOverloaded2 { (x, y) in x + y }
>> notOverloaded2 { _ in 1 }
>> 
>> // overloaded => resolve ambiguity on closure argument, when possible
>> overloaded { x, y in x + y }// "overloaded 1"
>> overloaded { (x, y) in x + y }  // "overloaded 1"
>> overloaded { t in t.lhs + t.rhs }   // "overloaded 2"
>> overloaded { (t) in t.lhs + t.rhs } // "overloaded 2”
> 
> This is exactly what happens today as a result of SE-0110 since the first two 
> calls take two arguments, and the next two take a single argument.

No, as a playground quickly reveals:

func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
"notOverloaded1" }
func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
return "notOverloaded3" }

// not overloaded => not ambiguous
notOverloaded1 { x, y in x + y }
notOverloaded1 { (x, y) in x + y }
notOverloaded1 { _ in 1 }  // Swift 4 error
notOverloaded2 { x, y in x + y }   // Swift 4 error
notOverloaded2 { (x, y) in x + y } // Swift 4 error
notOverloaded2 { _ in 1 }

Those errors are the famous regressions we want to fix.

>> overloaded { _ in 1 }   // error: ambiguous use of 
>> ‘overloaded'
> 
> With SE-0110 in its current form, this calls the tuple version since there is 
> a single closure parameter listed.

It would be nicer if. { _ in ... } would always mean "I don't care". With an 
ambiguity in the sample code we're looking at, and a compiler error.

The { (_, _) in ... } form is arguably cluttered, and it would be nicer it is 
was required only for disambiguition.

>> overloaded { (_) in 1 } // "overloaded 1”
> 
> With SE-0110 in its current form, this calls the tuple version since there is 
> a single closure parameter listed. I don’t understand why you would suggest 
> this should call the two-argument version since that’s inconsistent with the 
> other closures above that have a single argument.
> 
>> overloaded { (_, _) in 1 }  // "overloaded 2”
> 
> With SE-0110 in its current form, this calls the two-argument version since 
> there are two listed arguments.

I was wrong, sorry. I meant what you replied.

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Mark Lacey via swift-evolution

> On Jun 8, 2017, at 11:37 PM, Gwendal Roué via swift-evolution 
>  wrote:
> 
> 
>> Le 9 juin 2017 à 07:56, Vladimir.S via swift-evolution 
>> > a écrit :
>> 
>> Yes, we are discussing the *potential* solutions for Swift 4 that can 
>> decrease the pain of migration of *some* Swift3 code, given (Int,Int)->() 
>> and ((Int,Int))->() are different types in Swift 4.
>> 
>> But, as was said by Mark Lacey in this thread later, there is an "overload" 
>> problem for such solution, when closure of kind {x, y in ..} can be sent to 
>> overloaded func like here:
>> 
>> func overloaded(_ fn: (Int, Int) -> Int) { fn(1,2) }
>> func overloaded(_ fn: ((Int, Int)) -> Int) { fn((3,4)) }
>> 
>> overloaded { x, y in x + y }
>> overloaded { (x, y) in x + y }
>> 
>> Compiler is not able to determinate which type of closure do you want in 
>> each case. For ((Int,Int))->Int you still need some 'specific' syntax which 
>> disambiguate the call. So we *still* need some good syntax to destructure 
>> tuple argument in closure to use in place of ((Int,Int))->Int closure.
>> 
>> This means that there is no sense to allow very 'magic' {x,y in ..} syntax 
>> and compiler-detected type of closure if we still need good syntax 
>> for destructuring tuple argument in ((Int,Int))->().
> 
> Yes, Mark was very right asking about overloads. But is it a problem that 
> does not have a solution which preserves ergonomics?
> 
> func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
> "notOverloaded1" }
> func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
> return "notOverloaded3" }
> 
> func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
> "overloaded 1" }
> func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
> return "overloaded 2" }
> 
> // not overloaded => not ambiguous
> notOverloaded1 { x, y in x + y }
> notOverloaded1 { (x, y) in x + y }
> notOverloaded1 { _ in 1 }
> notOverloaded2 { x, y in x + y }
> notOverloaded2 { (x, y) in x + y }
> notOverloaded2 { _ in 1 }
> 
> // overloaded => resolve ambiguity on closure argument, when possible
> overloaded { x, y in x + y }// "overloaded 1"
> overloaded { (x, y) in x + y }  // "overloaded 1"
> overloaded { t in t.lhs + t.rhs }   // "overloaded 2"
> overloaded { (t) in t.lhs + t.rhs } // "overloaded 2”

This is exactly what happens today as a result of SE-0110 since the first two 
calls take two arguments, and the next two take a single argument.

> overloaded { _ in 1 }   // error: ambiguous use of 
> ‘overloaded'

With SE-0110 in its current form, this calls the tuple version since there is a 
single closure parameter listed.

> overloaded { (_) in 1 } // "overloaded 1”

With SE-0110 in its current form, this calls the tuple version since there is a 
single closure parameter listed. I don’t understand why you would suggest this 
should call the two-argument version since that’s inconsistent with the other 
closures above that have a single argument.

> overloaded { (_, _) in 1 }  // "overloaded 2”

With SE-0110 in its current form, this calls the two-argument version since 
there are two listed arguments.

Mark

> See the error on `overloaded { _ in 1 }`, because _ means "I don't care". 
> Well, here you have to care because of overloading. Ambiguity is resolved 
> with parenthesis. This is a specific behavior for `_`.
> 
> Gwendal
> 
> ---
> 
> PS, I had a little look at how Swift 3 currently behave with overloading ? 
> Badly, actually:
> 
> // SWIFT 3
> 
> func f(_ closure: (Int, Int) -> Int) -> String { return "two arguments" }
> // error: invalid redeclaration of 'f'
> // func f(_ closure: ((Int, Int)) -> Int) -> String { return "one 
> anonymous tuple argument" }
> func f(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { return "one 
> named tuple argument" }
> 
> // error: ambiguous use of 'f'
> // f { x, y in x + y }
> 
> f { t in t.rhs + t.lhs } // "one named tuple argument"
> 
> // error: ambiguous use of 'f'
> // f { t in t.0 + t.1 } // "one named tuple argument"
> 
> // error: ambiguous use of 'f'
> let c = { (a: Int, b: Int) -> Int in a + b }
> type(of: c) // ((Int, Int) -> Int).Type
> // error: ambiguous use of 'f'
> // f(c)
> 
> Swift 3 does not allow overloading ((Int, Int)) -> Int and (Int, Int) -> Int, 
> but allows overloading ((lhs: Int, rhs: Int)) -> Int and (Int, Int) -> Int.
> 
> Yet I could never call the (Int, Int) -> Int version, even when I provide 
> with a function that exactly matches its signature. And there are much too 
> many ambiguous situations the compiler can't deal with.
> 
> So yes, there is a problem with Swift 3.
> 
> How is it with Swift 4 (2017-06-02 snapshot)?
> 
> // 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-09 Thread Gwendal Roué via swift-evolution

> Le 9 juin 2017 à 07:56, Vladimir.S via swift-evolution 
>  a écrit :
> 
> Yes, we are discussing the *potential* solutions for Swift 4 that can 
> decrease the pain of migration of *some* Swift3 code, given (Int,Int)->() and 
> ((Int,Int))->() are different types in Swift 4.
> 
> But, as was said by Mark Lacey in this thread later, there is an "overload" 
> problem for such solution, when closure of kind {x, y in ..} can be sent to 
> overloaded func like here:
> 
> func overloaded(_ fn: (Int, Int) -> Int) { fn(1,2) }
> func overloaded(_ fn: ((Int, Int)) -> Int) { fn((3,4)) }
> 
> overloaded { x, y in x + y }
> overloaded { (x, y) in x + y }
> 
> Compiler is not able to determinate which type of closure do you want in each 
> case. For ((Int,Int))->Int you still need some 'specific' syntax which 
> disambiguate the call. So we *still* need some good syntax to destructure 
> tuple argument in closure to use in place of ((Int,Int))->Int closure.
> 
> This means that there is no sense to allow very 'magic' {x,y in ..} syntax 
> and compiler-detected type of closure if we still need good syntax 
> for destructuring tuple argument in ((Int,Int))->().

Yes, Mark was very right asking about overloads. But is it a problem that does 
not have a solution which preserves ergonomics?

func notOverloaded1(_ closure: (Int, Int) -> Int) -> String { return 
"notOverloaded1" }
func notOverloaded2(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
return "notOverloaded3" }

func overloaded(_ closure: (Int, Int) -> Int) -> String { return 
"overloaded 1" }
func overloaded(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { 
return "overloaded 2" }

// not overloaded => not ambiguous
notOverloaded1 { x, y in x + y }
notOverloaded1 { (x, y) in x + y }
notOverloaded1 { _ in 1 }
notOverloaded2 { x, y in x + y }
notOverloaded2 { (x, y) in x + y }
notOverloaded2 { _ in 1 }

// overloaded => resolve ambiguity on closure argument, when possible
overloaded { x, y in x + y }// "overloaded 1"
overloaded { (x, y) in x + y }  // "overloaded 1"
overloaded { t in t.lhs + t.rhs }   // "overloaded 2"
overloaded { (t) in t.lhs + t.rhs } // "overloaded 2"
overloaded { _ in 1 }   // error: ambiguous use of 'overloaded'
overloaded { (_) in 1 } // "overloaded 1"
overloaded { (_, _) in 1 }  // "overloaded 2"

See the error on `overloaded { _ in 1 }`, because _ means "I don't care". Well, 
here you have to care because of overloading. Ambiguity is resolved with 
parenthesis. This is a specific behavior for `_`.

Gwendal

---

PS, I had a little look at how Swift 3 currently behave with overloading ? 
Badly, actually:

// SWIFT 3

func f(_ closure: (Int, Int) -> Int) -> String { return "two arguments" }
// error: invalid redeclaration of 'f'
// func f(_ closure: ((Int, Int)) -> Int) -> String { return "one anonymous 
tuple argument" }
func f(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { return "one 
named tuple argument" }

// error: ambiguous use of 'f'
// f { x, y in x + y }

f { t in t.rhs + t.lhs } // "one named tuple argument"

// error: ambiguous use of 'f'
// f { t in t.0 + t.1 } // "one named tuple argument"

// error: ambiguous use of 'f'
let c = { (a: Int, b: Int) -> Int in a + b }
type(of: c) // ((Int, Int) -> Int).Type
// error: ambiguous use of 'f'
// f(c)

Swift 3 does not allow overloading ((Int, Int)) -> Int and (Int, Int) -> Int, 
but allows overloading ((lhs: Int, rhs: Int)) -> Int and (Int, Int) -> Int.

Yet I could never call the (Int, Int) -> Int version, even when I provide with 
a function that exactly matches its signature. And there are much too many 
ambiguous situations the compiler can't deal with.

So yes, there is a problem with Swift 3.

How is it with Swift 4 (2017-06-02 snapshot)?

// SWIFT 4

func f(_ closure: (Int, Int) -> Int) -> String { return "two arguments" }
// error: invalid redeclaration of 'f'
// func f(_ closure: ((Int, Int)) -> Int) -> String { return "one anonymous 
tuple argument" }
func f(_ closure: ((lhs: Int, rhs: Int)) -> Int) -> String { return "one 
named tuple argument" }

f { x, y in x + y }  // "two arguments"
f { t in t.rhs + t.lhs } // "one named tuple argument"
f { t in t.0 + t.1 } // "one named tuple argument"

let c = { (a: Int, b: Int) -> Int in a + b }
type(of: c)  // ((Int, Int) -> Int).Type
f(c) // "two arguments"

Much better.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution

On 09.06.2017 4:02, susan.dog...@gmail.com wrote:



Vladimir.S via swift-evolution  於 2017年6月9日 上午5:05 
寫道:

On 08.06.2017 21:17, Gwendal Roué via swift-evolution wrote:

Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
> a écrit :


On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
> wrote:

Well please no:


|let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|


Instead use destructuring sugar pitched by Chris Lattner on the other thread:

|let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|


I think this suggestion is better than the status quo. I'm wondering, though, if 
we should just drop the outer set of parentheses entirely, unless you're also 
putting types on the parameters. That is, a closure of type `(Int, Int) -> T` 
can look like this:

{ (x: Int, y: Int) in … }

Or it can look like this:

{ x, y in … }

But it *cannot* look like this:

{ (x, y) in … }

The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> T`, 
which immediately destructures the tuple parameter into separate constants.

--
Brent Royal-Gordon
Architechies

Hello,
There's a difference, in the mind of people here that try to show how bad were 
the recent changes, between:
1: closures defined independently
2: closures given as a parameter to a function.
I think that we all agree that the type of a closure that is defined 
independently should be well defined:
// Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
leta = { (x: Int, y: Int) -> Intin... }
letb = { ((x: Int, y: Int)) -> Intin... }
However, when a closure is given as an argument of a function that expects a 
closure, we ask for the maximum possible flexibility, as Swift 3 did:
funcwantsTwoArguments(_closure: (Int, Int) -> Int) { closure(1, 2) }
wantsTwoArguments{ a, b ina + b }
wantsTwoArguments{ (a, b) ina + b }
wantsTwoArguments{ t int.0+ t.1} // OK, maybe not
funcwantsATupleArgument(_closure: ((Int, Int)) -> Int) { closure((1, 2)) }
wantsATupleArgument{ a, b ina + b }
wantsATupleArgument{ (a, b) ina + b }
wantsATupleArgument{ t int.0+ t.1}
funcwantsANamedTupleArgument(_closure: ((lhs: Int, rhs: Int)) -> Int) { 
closure((lhs: 1, rhs: 2)) }
wantsANamedTupleArgument{ a, b ina + b }
wantsANamedTupleArgument{ (a, b) ina + b }
wantsANamedTupleArgument{ t int.lhs + t.rhs }


It's nice to see that we are agreed that func/closures declared separately 
should have clearly defined type and (at least for now) can't be 
interchangeable.

And personally I agree that this could be a solution to migration problem, 
compiler can generate closure of correct(requested) type if such closure:
1. declared inplace of func call as parameter of that func
2. has no type annotations for its arguments
3. (probably, can discuss) has no parenthesis for its arguments, because one pair 
of parenthesis in argument list declares closure of type (list of arguments)->T 
in other situations.

So, we can have

wantsTwoArguments{ a, b in a + b } // (Int,Int)->() will be generated
wantsTwoArguments{ (a, b) in a + b } // syntax of (Int,Int)->() closure

wantsATupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
wantsATupleArgument{ t in t.0+ t.1 } // syntax of ((Int,Int))->() closure

wantsANamedTupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
wantsANamedTupleArgument{ t in t.lhs + t.rhs } // syntax of ((Int,Int))->() 
closure


That's what Swift 3 has done now, but forbidden by Swift 4. Isn't it?


Yes, we are discussing the *potential* solutions for Swift 4 that can decrease the 
pain of migration of *some* Swift3 code, given (Int,Int)->() and ((Int,Int))->() are 
different types in Swift 4.


But, as was said by Mark Lacey in this thread later, there is an "overload" problem 
for such solution, when closure of kind {x, y in ..} can be sent to overloaded func 
like here:


func overloaded(_ fn: (Int, Int) -> Int) { fn(1,2) }
func overloaded(_ fn: ((Int, Int)) -> Int) { fn((3,4)) }

overloaded { x, y in x + y }
overloaded { (x, y) in x + y }

Compiler is not able to determinate which type of closure do you want in each case. 
For ((Int,Int))->Int you still need some 'specific' syntax which disambiguate the 
call. So we *still* need some good syntax to destructure tuple argument in closure to 
use in place of ((Int,Int))->Int closure.


This means that there is no sense to allow very 'magic' {x,y in ..} syntax and 
compiler-detected type of closure if we still need good syntax for 
destructuring tuple argument in ((Int,Int))->().





So, { a,b in ...} will be a special syntax for closure which type will be 
defined by compiler by type of func's parameter.

The question is if community and core team will support this idea, if that idea 
is better than other ideas like {((a,b)) in ..} for tuple deconstruction, and 
if this could be implemented before Swift 4 release.


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution

On 09.06.2017 0:31, Mark Lacey wrote:


On Jun 8, 2017, at 2:05 PM, Vladimir.S via swift-evolution 
> wrote:


On 08.06.2017 21:17, Gwendal Roué via swift-evolution wrote:
Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
> a écrit :


On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
 
> wrote:


Well please no:


|let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|


Instead use destructuring sugar pitched by Chris Lattner on the other thread:

|let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|

I think this suggestion is better than the status quo. I'm wondering, though, if 
we should just drop the outer set of parentheses entirely, unless you're also 
putting types on the parameters. That is, a closure of type `(Int, Int) -> T` can 
look like this:


{ (x: Int, y: Int) in … }

Or it can look like this:

{ x, y in … }

But it *cannot* look like this:

{ (x, y) in … }

The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> T`, 
which immediately destructures the tuple parameter into separate constants.


--
Brent Royal-Gordon
Architechies

Hello,
There's a difference, in the mind of people here that try to show how bad were the 
recent changes, between:

1: closures defined independently
2: closures given as a parameter to a function.
I think that we all agree that the type of a closure that is defined independently 
should be well defined:

// Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
leta = { (x: Int, y: Int) -> Intin... }
letb = { ((x: Int, y: Int)) -> Intin... }
However, when a closure is given as an argument of a function that expects a 
closure, we ask for the maximum possible flexibility, as Swift 3 did:

funcwantsTwoArguments(_closure: (Int, Int) -> Int) { closure(1, 2) }
wantsTwoArguments{ a, b ina + b }
wantsTwoArguments{ (a, b) ina + b }
wantsTwoArguments{ t int.0+ t.1} // OK, maybe not
funcwantsATupleArgument(_closure: ((Int, Int)) -> Int) { closure((1, 2)) }
wantsATupleArgument{ a, b ina + b }
wantsATupleArgument{ (a, b) ina + b }
wantsATupleArgument{ t int.0+ t.1}
funcwantsANamedTupleArgument(_closure: ((lhs: Int, rhs: Int)) -> Int) { 
closure((lhs: 1, rhs: 2)) }

wantsANamedTupleArgument{ a, b ina + b }
wantsANamedTupleArgument{ (a, b) ina + b }
wantsANamedTupleArgument{ t int.lhs + t.rhs }


It's nice to see that we are agreed that func/closures declared separately should 
have clearly defined type and (at least for now) can't be interchangeable.


And personally I agree that this could be a solution to migration problem, compiler 
can generate closure of correct(requested) type if such closure:

1. declared inplace of func call as parameter of that func
2. has no type annotations for its arguments
3. (probably, can discuss) has no parenthesis for its arguments, because one pair 
of parenthesis in argument list declares closure of type (list of arguments)->T in 
other situations.


So, we can have

wantsTwoArguments{ a, b in a + b } // (Int,Int)->() will be generated
wantsTwoArguments{ (a, b) in a + b } // syntax of (Int,Int)->() closure

wantsATupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
wantsATupleArgument{ t in t.0+ t.1 } // syntax of ((Int,Int))->() closure

wantsANamedTupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
wantsANamedTupleArgument{ t in t.lhs + t.rhs } // syntax of ((Int,Int))->() 
closure


Overloading complicates this. Ignoring for a moment that we cannot declare the 
following due to https://bugs.swift.org/browse/SR-5129:


func overloaded(_ fn: (Int, Int) -> Int) { fn(1,2) }
func overloaded(_ fn: ((Int, Int)) -> Int) { fn((3,4)) }
overloaded { x, y in x + y }
overloaded { (x, y) in x + y }



Good point! In this case, as I understand, this solution can't be considered as 
possible and we have(at this moment) only these possible directions:


1. Do not introduce any new syntax/sugar for this migration problem for now. 
Discuss/implement tuple destructuring / closures syntax after Swift 4 release.


2. Introduce new syntax for tuple argument destructuring in closure :
{((x,y)) in ..}
, this looks like good solution but not sure if it is the best and if this can block 
some future improvements here.


3. Introduce new 'let' syntax for tuple argument destructuring in closure :
{ let (x, y) in }
, also the same questions as for (2)

4. Allow type inference for tuple parts in already allowed syntax i.e. :
columns.index { (column: (name, _)) in column.name.lowercased() == 
lowercaseName }
, this will reduce the problem of migration and will not block any new improvements 
we can have in this area later, as this solution looks just as adding consistency for 
closure syntax: apply the same rule of type annotations but also 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Noah Desch via swift-evolution
As a "regular user" I wholeheartedly agree with everything Robert just said. 
Syntactic consistency between function parameters and closure parameters is a 
big win for usability and discoverability.

I actually did not know that it was possible to destructure tuples in closure 
arguments before this discussion happened. If the syntax had been more explicit 
and consistent (parens required for arguments and tuples as described below and 
in previous emails) I could have discovered this great feature on my own a long 
time ago.

-Noah Desch


> On Jun 8, 2017, at 5:39 PM, Robert Bennett via swift-evolution 
>  wrote:
> 
> Now, for closures, I think we should just apply the same principles. Require 
> parentheses for the arguments, which means double parentheses (or more) are 
> needed when unwrapping a tuple.
> 
> In my view cognitive load is a big part of ergonomics. Reducing the rule set 
> to a single principle seems very ergonomic to me.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Robert Bennett via swift-evolution
I’m personally a fan of strictness and maximum consistency. I like the idea of 
flattening single element tuples down to the deepest thing contained that is 
not a single element tuple. So (x) flattens to x and x,y flattens to 
the tuple (x,y). Past SEs have dictated that you may not flatten a tuple down 
into a list of arguments.

For function types, it’s a rule that you wrap the arguments in an extra set of 
parentheses, so (Int)->Int maps one Int to one Int; (Int, Int)->Int maps two 
(separate) Ints to Int; ((Int,Int))->Int and Int,Int->Int both map a 
2-tuple of Ints to Int. Int->Int is obviously not allowed.

Now, for closures, I think we should just apply the same principles. Require 
parentheses for the arguments, which means double parentheses (or more) are 
needed when unwrapping a tuple.

In my view cognitive load is a big part of ergonomics. Reducing the rule set to 
a single principle seems very ergonomic to me.

P.S. Maybe the compiler should also ban unnecessarily nested tuples, for 
clarity. Just a thought.

> On Jun 8, 2017, at 5:05 PM, Vladimir.S via swift-evolution 
>  wrote:
> 
> On 08.06.2017 21:17, Gwendal Roué via swift-evolution wrote:
>>> Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
>>> > a écrit :
>>> 
 On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
 > wrote:
 
 Well please no:
 
> |let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|
 
 Instead use destructuring sugar pitched by Chris Lattner on the other 
 thread:
 
 |let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|
 
>>> I think this suggestion is better than the status quo. I'm wondering, 
>>> though, if we should just drop the outer set of parentheses entirely, 
>>> unless you're also putting types on the parameters. That is, a closure of 
>>> type `(Int, Int) -> T` can look like this:
>>> 
>>> { (x: Int, y: Int) in … }
>>> 
>>> Or it can look like this:
>>> 
>>> { x, y in … }
>>> 
>>> But it *cannot* look like this:
>>> 
>>> { (x, y) in … }
>>> 
>>> The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> 
>>> T`, which immediately destructures the tuple parameter into separate 
>>> constants.
>>> 
>>> -- 
>>> Brent Royal-Gordon
>>> Architechies
>> Hello,
>> There's a difference, in the mind of people here that try to show how bad 
>> were the recent changes, between:
>> 1: closures defined independently
>> 2: closures given as a parameter to a function.
>> I think that we all agree that the type of a closure that is defined 
>> independently should be well defined:
>> // Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
>> leta = { (x: Int, y: Int) -> Intin... }
>> letb = { ((x: Int, y: Int)) -> Intin... }
>> However, when a closure is given as an argument of a function that expects a 
>> closure, we ask for the maximum possible flexibility, as Swift 3 did:
>> funcwantsTwoArguments(_closure: (Int, Int) -> Int) { closure(1, 2) }
>> wantsTwoArguments{ a, b ina + b }
>> wantsTwoArguments{ (a, b) ina + b }
>> wantsTwoArguments{ t int.0+ t.1} // OK, maybe not
>> funcwantsATupleArgument(_closure: ((Int, Int)) -> Int) { closure((1, 2)) }
>> wantsATupleArgument{ a, b ina + b }
>> wantsATupleArgument{ (a, b) ina + b }
>> wantsATupleArgument{ t int.0+ t.1}
>> funcwantsANamedTupleArgument(_closure: ((lhs: Int, rhs: Int)) -> Int) { 
>> closure((lhs: 1, rhs: 2)) }
>> wantsANamedTupleArgument{ a, b ina + b }
>> wantsANamedTupleArgument{ (a, b) ina + b }
>> wantsANamedTupleArgument{ t int.lhs + t.rhs }
> 
> It's nice to see that we are agreed that func/closures declared separately 
> should have clearly defined type and (at least for now) can't be 
> interchangeable.
> 
> And personally I agree that this could be a solution to migration problem, 
> compiler can generate closure of correct(requested) type if such closure:
> 1. declared inplace of func call as parameter of that func
> 2. has no type annotations for its arguments
> 3. (probably, can discuss) has no parenthesis for its arguments, because one 
> pair of parenthesis in argument list declares closure of type (list of 
> arguments)->T in other situations.
> 
> So, we can have
> 
> wantsTwoArguments{ a, b in a + b } // (Int,Int)->() will be generated
> wantsTwoArguments{ (a, b) in a + b } // syntax of (Int,Int)->() closure
> 
> wantsATupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
> wantsATupleArgument{ t in t.0+ t.1 } // syntax of ((Int,Int))->() closure
> 
> wantsANamedTupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
> wantsANamedTupleArgument{ t in t.lhs + t.rhs } // syntax of ((Int,Int))->() 
> closure
> 
> So, { a,b in ...} will be a special syntax for closure which type will be 
> defined by compiler by type of func's parameter.
> 
> The question is if community and 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Mark Lacey via swift-evolution

> On Jun 8, 2017, at 2:05 PM, Vladimir.S via swift-evolution 
>  wrote:
> 
> On 08.06.2017 21:17, Gwendal Roué via swift-evolution wrote:
>>> Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
>>>  
>>> >> a 
>>> écrit :
>>> 
 On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
 > wrote:
 
 Well please no:
 
> |let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|
 
 Instead use destructuring sugar pitched by Chris Lattner on the other 
 thread:
 
 |let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|
 
>>> I think this suggestion is better than the status quo. I'm wondering, 
>>> though, if we should just drop the outer set of parentheses entirely, 
>>> unless you're also putting types on the parameters. That is, a closure of 
>>> type `(Int, Int) -> T` can look like this:
>>> 
>>> { (x: Int, y: Int) in … }
>>> 
>>> Or it can look like this:
>>> 
>>> { x, y in … }
>>> 
>>> But it *cannot* look like this:
>>> 
>>> { (x, y) in … }
>>> 
>>> The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> 
>>> T`, which immediately destructures the tuple parameter into separate 
>>> constants.
>>> 
>>> -- 
>>> Brent Royal-Gordon
>>> Architechies
>> Hello,
>> There's a difference, in the mind of people here that try to show how bad 
>> were the recent changes, between:
>> 1: closures defined independently
>> 2: closures given as a parameter to a function.
>> I think that we all agree that the type of a closure that is defined 
>> independently should be well defined:
>> // Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
>> leta = { (x: Int, y: Int) -> Intin... }
>> letb = { ((x: Int, y: Int)) -> Intin... }
>> However, when a closure is given as an argument of a function that expects a 
>> closure, we ask for the maximum possible flexibility, as Swift 3 did:
>> funcwantsTwoArguments(_closure: (Int, Int) -> Int) { closure(1, 2) }
>> wantsTwoArguments{ a, b ina + b }
>> wantsTwoArguments{ (a, b) ina + b }
>> wantsTwoArguments{ t int.0+ t.1} // OK, maybe not
>> funcwantsATupleArgument(_closure: ((Int, Int)) -> Int) { closure((1, 2)) }
>> wantsATupleArgument{ a, b ina + b }
>> wantsATupleArgument{ (a, b) ina + b }
>> wantsATupleArgument{ t int.0+ t.1}
>> funcwantsANamedTupleArgument(_closure: ((lhs: Int, rhs: Int)) -> Int) { 
>> closure((lhs: 1, rhs: 2)) }
>> wantsANamedTupleArgument{ a, b ina + b }
>> wantsANamedTupleArgument{ (a, b) ina + b }
>> wantsANamedTupleArgument{ t int.lhs + t.rhs }
> 
> It's nice to see that we are agreed that func/closures declared separately 
> should have clearly defined type and (at least for now) can't be 
> interchangeable.
> 
> And personally I agree that this could be a solution to migration problem, 
> compiler can generate closure of correct(requested) type if such closure:
> 1. declared inplace of func call as parameter of that func
> 2. has no type annotations for its arguments
> 3. (probably, can discuss) has no parenthesis for its arguments, because one 
> pair of parenthesis in argument list declares closure of type (list of 
> arguments)->T in other situations.
> 
> So, we can have
> 
> wantsTwoArguments{ a, b in a + b } // (Int,Int)->() will be generated
> wantsTwoArguments{ (a, b) in a + b } // syntax of (Int,Int)->() closure
> 
> wantsATupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
> wantsATupleArgument{ t in t.0+ t.1 } // syntax of ((Int,Int))->() closure
> 
> wantsANamedTupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
> wantsANamedTupleArgument{ t in t.lhs + t.rhs } // syntax of ((Int,Int))->() 
> closure

Overloading complicates this. Ignoring for a moment that we cannot declare the 
following due to https://bugs.swift.org/browse/SR-5129: 


func overloaded(_ fn: (Int, Int) -> Int) { fn(1,2) }
func overloaded(_ fn: ((Int, Int)) -> Int) { fn((3,4)) }
  
overloaded { x, y in x + y }
overloaded { (x, y) in x + y }


Mark

> 
> So, { a,b in ...} will be a special syntax for closure which type will be 
> defined by compiler by type of func's parameter.
> 
> The question is if community and core team will support this idea, if that 
> idea is better than other ideas like {((a,b)) in ..} for tuple 
> deconstruction, and if this could be implemented before Swift 4 release.
> 
>> *This gives us the ability to deal with unfitted function signatures.* For 
>> example, most Dictionary methods. Yes, they are usually unfitted:
>> extensionDictionary{
>> funcforEach(_body: ((key: Key, value: Value)) throws-> Void) rethrows
>> }
>> Who cares about this named (key:value:) tuple? Absolutely nobody, as 
>> exemplified by this remarquable Swift 3 snippet below, where no tuple, no 
>> `key`, and no 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Daryle Walker via swift-evolution

> On Jun 7, 2017, at 11:12 PM, Stephen Celis via swift-evolution 
>  wrote:
> 
>> On Jun 7, 2017, at 10:33 PM, Xiaodi Wu via swift-evolution 
>>  wrote:
>> 
>> However, what I don’t get is why you’d have a mismatch here. Your method 
>> `first` accepts a closure, and surely the type it expects should be 
>> `((String, Conversation)) -> Bool` instead, since that is the type that the 
>> `filter` method expects in the body of your implementation?
> 
> I must continue to ask for more justification as to why it's _so_ valuable to 
> consider "(Int,Int)->()" and "((Int,Int))->()" to be different in _most_ 
> cases. Even in the contrived-described example above, the function may be 
> reusable and the engineer may pass "String" and "Conversation" objects 
> directly in some cases, and this distinction only makes things more difficult 
> and requires cumbersome workarounds.

Imagine if “(Int, Int)” was hidden behind a type-alias. You expect you’d be 
entering a single argument. But, surprise, you unintentionally activated the 
secret tuple-exploding mode and you’re actually passing in two arguments!

[I didn’t follow the original discussion, so apologies if using a type-alias 
doesn’t case tuple-explosion. Of course, that would be a different code smell….]

— 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com 

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution

On 08.06.2017 20:40, Brent Royal-Gordon via swift-evolution wrote:
On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
> wrote:


Well please no:


|let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

|let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|

I think this suggestion is better than the status quo. I'm wondering, though, if we 
should just drop the outer set of parentheses entirely, unless you're also putting 
types on the parameters. That is, a closure of type `(Int, Int) -> T` can look like this:


{ (x: Int, y: Int) in … }

Or it can look like this:

{ x, y in … }

But it *cannot* look like this:

{ (x, y) in … }

The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> T`, which 
immediately destructures the tuple parameter into separate constants.


The main problem with this suggestion, as I understand, is that {(x,y) in ..} in 
Swift 3 is allowed for (Int,Int)->() closure. So, your proposal will also broke code 
during the migration as ((Int,Int))->() will be sent where (Int,Int)->() is expected.


Also, personally, I see a big inconsistency when
{ (x: Int, y: Int) in ..}
declares closure of type (Int,Int)->(), but
{ (x, y) in ... }
for some reason declared closure of type ((Int,Int))->()
while currently we know that we are allowed to just omit type annotation in 
closures.

And it seems naturally for me to see { ((x,y)) in ..} for closure of type 
((Int,Int))->() - there is nice symmetry about these two pairs of parenthesis in 
closure and in type syntax itself.




--
Brent Royal-Gordon
Architechies



___
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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution

On 08.06.2017 21:17, Gwendal Roué via swift-evolution wrote:


Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
> a écrit :


On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
> wrote:


Well please no:


|let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

|let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|

I think this suggestion is better than the status quo. I'm wondering, though, if we 
should just drop the outer set of parentheses entirely, unless you're also putting 
types on the parameters. That is, a closure of type `(Int, Int) -> T` can look like 
this:


{ (x: Int, y: Int) in … }

Or it can look like this:

{ x, y in … }

But it *cannot* look like this:

{ (x, y) in … }

The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> T`, 
which immediately destructures the tuple parameter into separate constants.


--
Brent Royal-Gordon
Architechies


Hello,

There's a difference, in the mind of people here that try to show how bad were the 
recent changes, between:


1: closures defined independently
2: closures given as a parameter to a function.

I think that we all agree that the type of a closure that is defined independently 
should be well defined:


// Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
leta = { (x: Int, y: Int) -> Intin... }
letb = { ((x: Int, y: Int)) -> Intin... }

However, when a closure is given as an argument of a function that expects a closure, 
we ask for the maximum possible flexibility, as Swift 3 did:


funcwantsTwoArguments(_closure: (Int, Int) -> Int) { closure(1, 2) }
wantsTwoArguments{ a, b ina + b }
wantsTwoArguments{ (a, b) ina + b }
wantsTwoArguments{ t int.0+ t.1} // OK, maybe not

funcwantsATupleArgument(_closure: ((Int, Int)) -> Int) { closure((1, 2)) }
wantsATupleArgument{ a, b ina + b }
wantsATupleArgument{ (a, b) ina + b }
wantsATupleArgument{ t int.0+ t.1}


funcwantsANamedTupleArgument(_closure: ((lhs: Int, rhs: Int)) -> Int) { closure((lhs: 
1, rhs: 2)) }

wantsANamedTupleArgument{ a, b ina + b }
wantsANamedTupleArgument{ (a, b) ina + b }
wantsANamedTupleArgument{ t int.lhs + t.rhs }



It's nice to see that we are agreed that func/closures declared separately should 
have clearly defined type and (at least for now) can't be interchangeable.


And personally I agree that this could be a solution to migration problem, compiler 
can generate closure of correct(requested) type if such closure:

1. declared inplace of func call as parameter of that func
2. has no type annotations for its arguments
3. (probably, can discuss) has no parenthesis for its arguments, because one pair of 
parenthesis in argument list declares closure of type (list of arguments)->T in other 
situations.


So, we can have

wantsTwoArguments{ a, b in a + b } // (Int,Int)->() will be generated
wantsTwoArguments{ (a, b) in a + b } // syntax of (Int,Int)->() closure

wantsATupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
wantsATupleArgument{ t in t.0+ t.1 } // syntax of ((Int,Int))->() closure

wantsANamedTupleArgument{ a, b in a + b } // ((Int,Int))->() will be generated
wantsANamedTupleArgument{ t in t.lhs + t.rhs } // syntax of ((Int,Int))->() 
closure

So, { a,b in ...} will be a special syntax for closure which type will be defined by 
compiler by type of func's parameter.


The question is if community and core team will support this idea, if that idea is 
better than other ideas like {((a,b)) in ..} for tuple deconstruction, and if this 
could be implemented before Swift 4 release.


*This gives us the ability to deal with unfitted function signatures.* For example, 
most Dictionary methods. Yes, they are usually unfitted:


extensionDictionary{
funcforEach(_body: ((key: Key, value: Value)) throws-> Void) rethrows
 }

Who cares about this named (key:value:) tuple? Absolutely nobody, as exemplified by 
this remarquable Swift 3 snippet below, where no tuple, no `key`, and no `value` is 
in sight:


letscores: [String: Int] = ... // [playerName: score]
 scores.forEach { name, score in
print("\(name): \(score)")
 }

Do you see?


let scores: [String: Int] = ["a":1, "b":2]

scores.forEach { (score: (name:String, value:Int)) in
print("\(score.name): \(score.value)")
}

I'm not saying that this syntax as good as in your example, but it is not as bad/ugly 
as you say.




Gwendal




___
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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread David Hart via swift-evolution
Side note: when converting a project to Swift 4, I’ve encountered quite a few 
Quality of Life regressions that could also be related:

Regression 1

When using this library https://github.com/socketio/socket.io-client-swift:

public typealias NormalCallback = ([Any], SocketAckEmitter) -> Void

class Socket {
func on(_ event: String, callback: @escaping NormalCallback) -> UUID { … }
}

My code had to be modified from:

socket.on(“message”) { _ in
print(“got message")
}

to:

socket.on(“message”) { (_, _) in
print(“got message")
}

Regression 2

When using RxSwift: https://github.com/ReactiveX/RxSwift 
 (simplified example):

public class Driver {
func drive(onNext: ((E) -> Void)) -> Disposable {}
}

I had to change the following code:

let driver: Driver = …
driver.drive(onNext: {
print(“onNext")
})

to:

let driver: Driver = …
driver.drive(onNext { _ in
print(“onNext")
})

Regression 3

Also with RxSwift (simplified example):

public class Driver {
func onNext(_ element: E) { … }
}

I had to change the following code:

let driver: Driver = …
driver.onNext()

to:

let driver: Driver = …
driver.onNext(())

Conclusion

Basically, these regressions add synctactic pollution to quite a few cases 
turning around tuples and Void.

David.

> On 8 Jun 2017, at 12:08, David Hart via swift-evolution 
>  wrote:
> 
>> 
>> On 8 Jun 2017, at 11:17, Gwendal Roué via swift-evolution 
>> > wrote:
>> 
>> 
>>> Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
>>> > a écrit :
>>> 
 On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
 > wrote:
 
 Well please no:
 
 
  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
 
 Instead use destructuring sugar pitched by Chris Lattner on the other 
 thread:
 
 let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
 
>>> 
>>> I think this suggestion is better than the status quo. I'm wondering, 
>>> though, if we should just drop the outer set of parentheses entirely, 
>>> unless you're also putting types on the parameters. That is, a closure of 
>>> type `(Int, Int) -> T` can look like this:
>>> 
>>> { (x: Int, y: Int) in … }
>>> 
>>> Or it can look like this:
>>> 
>>> { x, y in … }
>>> 
>>> But it *cannot* look like this:
>>> 
>>> { (x, y) in … }
>>> 
>>> The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> 
>>> T`, which immediately destructures the tuple parameter into separate 
>>> constants.
>>> 
>>> -- 
>>> Brent Royal-Gordon
>>> Architechies
>> 
>> Hello,
>> 
>> There's a difference, in the mind of people here that try to show how bad 
>> were the recent changes, between:
>> 
>> 1: closures defined independently
>> 2: closures given as a parameter to a function.
>> 
>> I think that we all agree that the type of a closure that is defined 
>> independently should be well defined:
>> 
>> // Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
>> let a = { (x: Int, y: Int) -> Int in ... }
>> let b = { ((x: Int, y: Int)) -> Int in ... }
>> 
>> However, when a closure is given as an argument of a function that expects a 
>> closure, we ask for the maximum possible flexibility, as Swift 3 did:
>> 
>> func wantsTwoArguments(_ closure: (Int, Int) -> Int) { closure(1, 2) }
>> wantsTwoArguments { a, b in a + b }
>> wantsTwoArguments { (a, b) in a + b }
>> wantsTwoArguments { t in t.0 + t.1 } // OK, maybe not
>> 
>> func wantsATupleArgument(_ closure: ((Int, Int)) -> Int) { closure((1, 
>> 2)) }
>> wantsATupleArgument { a, b in a + b }
>> wantsATupleArgument { (a, b) in a + b }
>> wantsATupleArgument { t in t.0 + t.1 }
>> 
>> func wantsANamedTupleArgument(_ closure: ((lhs: Int, rhs: Int)) -> Int) 
>> { closure((lhs: 1, rhs: 2)) }
>> wantsANamedTupleArgument { a, b in a + b }
>> wantsANamedTupleArgument { (a, b) in a + b }
>> wantsANamedTupleArgument { t in t.lhs + t.rhs }
>> 
>> This gives us the ability to deal with unfitted function signatures. For 
>> example, most Dictionary methods. Yes, they are usually unfitted:
>> 
>> extension Dictionary {
>> func forEach(_ body: ((key: Key, value: Value)) throws -> Void) 
>> rethrows
>> }
>> 
>> Who cares about this named (key:value:) tuple? Absolutely nobody, as 
>> exemplified by this remarquable Swift 3 snippet below, where no tuple, no 
>> `key`, and no `value` is in sight:
>> 
>> let scores: [String: Int] = ... // [playerName: score]
>> scores.forEach { name, score in
>> print("\(name): \(score)")
>> }
>> 
>> Do you see?
> 
> This post is the one that makes most sense to me! Be strict on definition but 
> flexible on use.
> 
>> Gwendal
>> 
>> 
>> 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread David Hart via swift-evolution

> On 8 Jun 2017, at 11:17, Gwendal Roué via swift-evolution 
>  wrote:
> 
> 
>> Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
>> > a écrit :
>> 
>>> On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
>>> > wrote:
>>> 
>>> Well please no:
>>> 
>>> 
>>>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
>>> 
>>> Instead use destructuring sugar pitched by Chris Lattner on the other 
>>> thread:
>>> 
>>> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>>> 
>> 
>> I think this suggestion is better than the status quo. I'm wondering, 
>> though, if we should just drop the outer set of parentheses entirely, unless 
>> you're also putting types on the parameters. That is, a closure of type 
>> `(Int, Int) -> T` can look like this:
>> 
>>  { (x: Int, y: Int) in … }
>> 
>> Or it can look like this:
>> 
>>  { x, y in … }
>> 
>> But it *cannot* look like this:
>> 
>>  { (x, y) in … }
>> 
>> The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> 
>> T`, which immediately destructures the tuple parameter into separate 
>> constants.
>> 
>> -- 
>> Brent Royal-Gordon
>> Architechies
> 
> Hello,
> 
> There's a difference, in the mind of people here that try to show how bad 
> were the recent changes, between:
> 
> 1: closures defined independently
> 2: closures given as a parameter to a function.
> 
> I think that we all agree that the type of a closure that is defined 
> independently should be well defined:
> 
> // Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
> let a = { (x: Int, y: Int) -> Int in ... }
> let b = { ((x: Int, y: Int)) -> Int in ... }
> 
> However, when a closure is given as an argument of a function that expects a 
> closure, we ask for the maximum possible flexibility, as Swift 3 did:
> 
> func wantsTwoArguments(_ closure: (Int, Int) -> Int) { closure(1, 2) }
> wantsTwoArguments { a, b in a + b }
> wantsTwoArguments { (a, b) in a + b }
> wantsTwoArguments { t in t.0 + t.1 } // OK, maybe not
> 
> func wantsATupleArgument(_ closure: ((Int, Int)) -> Int) { closure((1, 
> 2)) }
> wantsATupleArgument { a, b in a + b }
> wantsATupleArgument { (a, b) in a + b }
> wantsATupleArgument { t in t.0 + t.1 }
> 
> func wantsANamedTupleArgument(_ closure: ((lhs: Int, rhs: Int)) -> Int) { 
> closure((lhs: 1, rhs: 2)) }
> wantsANamedTupleArgument { a, b in a + b }
> wantsANamedTupleArgument { (a, b) in a + b }
> wantsANamedTupleArgument { t in t.lhs + t.rhs }
> 
> This gives us the ability to deal with unfitted function signatures. For 
> example, most Dictionary methods. Yes, they are usually unfitted:
> 
> extension Dictionary {
> func forEach(_ body: ((key: Key, value: Value)) throws -> Void) 
> rethrows
> }
> 
> Who cares about this named (key:value:) tuple? Absolutely nobody, as 
> exemplified by this remarquable Swift 3 snippet below, where no tuple, no 
> `key`, and no `value` is in sight:
> 
> let scores: [String: Int] = ... // [playerName: score]
> scores.forEach { name, score in
> print("\(name): \(score)")
> }
> 
> Do you see?

This post is the one that makes most sense to me! Be strict on definition but 
flexible on use.

> Gwendal
> 
> 
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Gwendal Roué via swift-evolution

> Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
>  a écrit :
> 
>> On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
>> > wrote:
>> 
>> Well please no:
>> 
>> 
>>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
>> 
>> Instead use destructuring sugar pitched by Chris Lattner on the other thread:
>> 
>> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>> 
> 
> I think this suggestion is better than the status quo. I'm wondering, though, 
> if we should just drop the outer set of parentheses entirely, unless you're 
> also putting types on the parameters. That is, a closure of type `(Int, Int) 
> -> T` can look like this:
> 
>   { (x: Int, y: Int) in … }
> 
> Or it can look like this:
> 
>   { x, y in … }
> 
> But it *cannot* look like this:
> 
>   { (x, y) in … }
> 
> The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> 
> T`, which immediately destructures the tuple parameter into separate 
> constants.

I better understand your message. It does look good at first sight.

But... The full picture needs to be completed with closures of type `((Int, 
Int)) -> T` and `((lsh: Int, rhs: Int)) -> T`. Those are among the most 
*interesting* in the regressions they brought.

Will there be any forbidden syntax as well? What about unfitted signatures, 
which I talked just before?

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Gwendal Roué via swift-evolution

> Le 8 juin 2017 à 20:17, Gwendal Roué  a écrit :
> 
> This gives us the ability to deal with unfitted function signatures. For 
> example, most Dictionary methods. Yes, they are usually unfitted:
> 
> extension Dictionary {
> func forEach(_ body: ((key: Key, value: Value)) throws -> Void) 
> rethrows
> }
> 
> Who cares about this named (key:value:) tuple? Absolutely nobody, as 
> exemplified by this remarquable Swift 3 snippet below, where no tuple, no 
> `key`, and no `value` is in sight:
> 
> let scores: [String: Int] = ... // [playerName: score]
> scores.forEach { name, score in
> print("\(name): \(score)")
> }
> 
> Do you see?

I regret my "Absolutely nobody" snippet. Some people like the `key` and `value` 
identifiers.

Those people are the people who write the standard library, people who write 
blog posts about Swift novelties, and people who write experimental software 
around Swift. All very valuable people.

There are other kinds of developers, who don't really care about the beauty of 
dictionary design and implementation. They just want a container that does what 
it's supposed to do: map stuff to other stuff. Not keys to values.

To them, a dictionary is like a screwdriver: when you use it, you don't want to 
think about it much.

And the recent changes force us to see uninteresting implementation details 
that obscure everyday code.

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Adrian Zubarev via swift-evolution
At first glance, this makes totally sense to me, feel free to push this idea on 
the main discussion thread about this dilemma. :)



-- 
Adrian Zubarev
Sent with Airmail

Am 8. Juni 2017 um 19:41:03, Brent Royal-Gordon (br...@architechies.com) 
schrieb:

On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
 wrote:

Well please no:


 let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }

I think this suggestion is better than the status quo. I'm wondering, though, 
if we should just drop the outer set of parentheses entirely, unless you're 
also putting types on the parameters. That is, a closure of type `(Int, Int) -> 
T` can look like this:

{ (x: Int, y: Int) in … }

Or it can look like this:

{ x, y in … }

But it *cannot* look like this:

{ (x, y) in … }

The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> T`, 
which immediately destructures the tuple parameter into separate constants.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Gwendal Roué via swift-evolution

> Le 8 juin 2017 à 19:40, Brent Royal-Gordon via swift-evolution 
>  a écrit :
> 
>> On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
>> > wrote:
>> 
>> Well please no:
>> 
>> 
>>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
>> 
>> Instead use destructuring sugar pitched by Chris Lattner on the other thread:
>> 
>> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>> 
> 
> I think this suggestion is better than the status quo. I'm wondering, though, 
> if we should just drop the outer set of parentheses entirely, unless you're 
> also putting types on the parameters. That is, a closure of type `(Int, Int) 
> -> T` can look like this:
> 
>   { (x: Int, y: Int) in … }
> 
> Or it can look like this:
> 
>   { x, y in … }
> 
> But it *cannot* look like this:
> 
>   { (x, y) in … }
> 
> The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> 
> T`, which immediately destructures the tuple parameter into separate 
> constants.
> 
> -- 
> Brent Royal-Gordon
> Architechies

Hello,

There's a difference, in the mind of people here that try to show how bad were 
the recent changes, between:

1: closures defined independently
2: closures given as a parameter to a function.

I think that we all agree that the type of a closure that is defined 
independently should be well defined:

// Choose between (Int, Int) -> () or ((x: Int, y: Int)) -> ()
let a = { (x: Int, y: Int) -> Int in ... }
let b = { ((x: Int, y: Int)) -> Int in ... }

However, when a closure is given as an argument of a function that expects a 
closure, we ask for the maximum possible flexibility, as Swift 3 did:

func wantsTwoArguments(_ closure: (Int, Int) -> Int) { closure(1, 2) }
wantsTwoArguments { a, b in a + b }
wantsTwoArguments { (a, b) in a + b }
wantsTwoArguments { t in t.0 + t.1 } // OK, maybe not

func wantsATupleArgument(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
wantsATupleArgument { a, b in a + b }
wantsATupleArgument { (a, b) in a + b }
wantsATupleArgument { t in t.0 + t.1 }

func wantsANamedTupleArgument(_ closure: ((lhs: Int, rhs: Int)) -> Int) { 
closure((lhs: 1, rhs: 2)) }
wantsANamedTupleArgument { a, b in a + b }
wantsANamedTupleArgument { (a, b) in a + b }
wantsANamedTupleArgument { t in t.lhs + t.rhs }

This gives us the ability to deal with unfitted function signatures. For 
example, most Dictionary methods. Yes, they are usually unfitted:

extension Dictionary {
func forEach(_ body: ((key: Key, value: Value)) throws -> Void) rethrows
}

Who cares about this named (key:value:) tuple? Absolutely nobody, as 
exemplified by this remarquable Swift 3 snippet below, where no tuple, no 
`key`, and no `value` is in sight:

let scores: [String: Int] = ... // [playerName: score]
scores.forEach { name, score in
print("\(name): \(score)")
}

Do you see?

Gwendal


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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Jens Persson via swift-evolution
On Thu, Jun 8, 2017 at 7:20 PM, Víctor Pimentel Rodríguez via
swift-evolution  wrote:
>
> /../ I'm really going to miss being able to model every type of closure
> with the type (T) -> U
>

Me too, and I can also see what you mean regarding the "tone" of some of
the proposals. Tuple splat (or rather the whole "universal tuple concept")
would certainly have been an extremely powerful and elegant feature (I
really can't understand why they decided to call it "cute" in the
proposal), if it had worked all the way, without creating inconsistencies
and questions (inout, variadics etc).

However, I don't see any other way forward than to properly implement
SE-0110 et al, and then work from there.

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Brent Royal-Gordon via swift-evolution
> On Jun 7, 2017, at 3:03 AM, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> Well please no:
> 
> 
>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
> 
> Instead use destructuring sugar pitched by Chris Lattner on the other thread:
> 
> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
> 

I think this suggestion is better than the status quo. I'm wondering, though, 
if we should just drop the outer set of parentheses entirely, unless you're 
also putting types on the parameters. That is, a closure of type `(Int, Int) -> 
T` can look like this:

{ (x: Int, y: Int) in … }

Or it can look like this:

{ x, y in … }

But it *cannot* look like this:

{ (x, y) in … }

The `(x, y)` form can instead be a closure of a type like `((Int, Int)) -> T`, 
which immediately destructures the tuple parameter into separate constants.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Víctor Pimentel Rodríguez via swift-evolution
On Thu, Jun 8, 2017 at 3:01 PM, Vladimir.S  wrote:

> On 08.06.2017 12:17, Víctor Pimentel Rodríguez via swift-evolution wrote:
>
>> On Thu, Jun 8, 2017 at 5:15 AM, Susan Cheng via swift-evolution <
>> swift-evolution@swift.org > wrote:
>>
>> Just a thought
>>
>> if parentheses is important, why the tuples are not?
>>
>>
>> This is stated on the proposal (and not in previous proposals):
>>
>> https://github.com/apple/swift-evolution/blob/master/proposa
>> ls/0110-distingish-single-tuple-arg.md
>>
>>   *
>>
>> We understand that this may be a departure from the current
>> convention that a set
>> of parentheses enclosing a single object are considered semantically
>> meaningless,
>> but it is the most natural way to differentiate between the two
>> situations
>> described above and would be a clearly-delineated one-time-only
>> exception.
>>
>>
>> > als/0110-distingish-single-tuple-arg.md#impact-on-existing-code>
>>
>> This proposal marks a one-time-only exception, to differentiate the
>> parenthesis needed to enclose a list of closure parameters and the
>> parenthesis needed for tuples. That's adding an exception for implementing
>> a regression.
>>
>> The more I think about it, the more I hate* this proposal.
>>
>> * Well, not _hate_, let's say slightly dislike :P
>>
>
> Please look here:
> https://github.com/apple/swift-evolution/blob/master/proposa
> ls/0066-standardize-function-type-syntax.md
>
> into "Proposed solution" section:
>
> Parentheses will be required in function types. Examples:
>
> Int -> Int   // error
> (Int) -> Int // function from Int to Int
> ((Int)) -> Int   // also function from Int to Int
>
> Int, Int -> Int  // error
> (Int, Int) -> Int// function from Int and Int to Int
> ((Int, Int)) -> Int  // function from tuple (Int, Int) to Int
>
> let f: () -> Int // function with no parameters
> let g: (()) -> Int   // function taking a single () parameter
> let h: ((())) -> Int // function taking a single () parameter
>
> f();   g(()); h(())  // correct
> f(()); g();   h()// errors
>
> Do you also hate* SE-0066?


I'm certainly not a fan, although I must say that it's funny to me to think
of the usefulness of a closure that only accepts a single parameter of type
"()", and how important it's to be able to model it. It was beautiful to me
how tuples and closure arguments were interchangeable, and I hope that some
day that feature will be back.

I'm also not a fan of SE-0029, the original proposal that removed tuple
splat and linked from SE-0110. I'm fine if it was better for the compiler
to remove that hacky implementation, but that proposal certainly has some
disdain for implicit tuple splat:

> This doesn’t seem like a positive contribution - this seems like a
"clever" feature, not a practical one.

And going back to SE-0110, I dislike this part too:

> The current behavior violates the principle of least surprise

People seems to get more surprised when you migrate some perfectly
reasonable code and have to use an intermediate tuple to achieve the same
effect as the code example in SE-0110 shows.

After rereading the proposals the motivation sections read more like "we
don't like this feature and it's useless" more than "we don't like this
implementation and it's dragging us". Looking at the final implementation
of this proposal (the third one!), I don't think the resulting code is
easier to maintain, actually the Swift 4 mode seems more complex:

https://github.com/apple/swift/pull/6133/files

I'm sorry, but I like this feature. Apart from Dictionary and similar, I'm
really going to miss being able to model every type of closure with the
type (T) -> U.

-- 
Víctor Pimentel
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Jens Persson via swift-evolution
I just want to say, as a "regular developer", that I'm with Vladimir S here.

Swift 3 (and current Swift 4) both still have a lot of inconsistencies
and/or bugs related to tuple- and function types which will need to be
fixed before ABI stability, and they are not fixed by going back to a state
with even more inconsistencies.

FWIW I can't see how SE-0110 can be considered fully implemented, and this
is simply because the most recent compiler still cannot properly
"Distinguish between single-tuple and multiple-argument function types"
(that's the title of SE-0110), this is evident in lots of different ways,
here are some of them:

https://bugs.swift.org/browse/SR-5127
Single-tuple and multiple-argument function types should not be considered
equal

https://bugs.swift.org/browse/SR-5128
Don't allow swapping a single-tuple function with a multiple-argument
function

https://bugs.swift.org/browse/SR-5129
Don't treat func signatures as being the same when they are in fact
different

https://bugs.swift.org/browse/SR-5130
Single-tuple and multiple-argument function types should be treated as
different types

I think of the "regression"/decreased ergonomics as a price that is worth
paying for, and a necessary step towards, getting the language in a state
in which it is possible to get rid of Swift's current parentheses-related
inconsistencies and possibly reimplement the hopefully just temporarily
lost ergonomics and/or expressiveness.

Another related "regression" that I think is worth noting has to do with
generics, namely the inability to have type parameters for function types
in this form: Parameter -> Result. This is no longer possible in Swift 4
and it will instead require special casing for each number of parameters in
the function types. This means that it is also impossible to make a type
generic over just function types (wihtout special casing for parameter
count). These things were (sort of) possible to do in earlier versions, but
they couldn't make it all the way without other parts of the language
falling apart. They certainly hinted about something nice, and maybe if the
language is allowed to be simplified and made more consistent, they can be
reimplemented in a proper way.

/Jens


On Thu, Jun 8, 2017 at 3:26 PM, Vladimir.S via swift-evolution <
swift-evolution@swift.org> wrote:

> On 08.06.2017 9:43, Jonathan Hull wrote:
>
>> Also, I want to repeat what I said on the other thread.  We should revert
>> to Swift 3 behavior for this, and then take the time to design the behavior
>> we really want (either for 4.1 or 5).  Anything else will cause us to break
>> people’s code twice…
>>
>
> Yes, *just* ignore/revert a number of connected, actively discussed and
> accepted, implemented(partially for some) proposals, freeze the current
> broken state of function types for very long period without any ability in
> near feature to fix it.
>
> Instead of improvement of the syntax of the problematic parts of code even
> after release (if not possible to suggest a suitable solution before the
> release). I don't think that *improvements* in syntax can break people's
> code.
>
> Huh..
>
>
>> Thanks,
>> Jon
>>
>> On Jun 7, 2017, at 11:50 AM, Gwendal Roué via swift-evolution <
>>> swift-evolution@swift.org > wrote:
>>>
>>>
>>>
>>> Le 7 juin 2017 à 20:33, Gwendal Roué >> gwendal.r...@gmail.com>> a écrit :

 For example, take those three functions:

 func f(_ closure:(Int, Int) -> ())
 func g(_ closure:((Int, Int)) -> ())
 func h(_ closure:((a: Int, b: Int)) -> ())

 If one can always write (as in Swift 3):

 f { (a, b) in ... }
 g { (a, b) in ... }
 c { (a, b) in ... }

 Then one can easily deal with a badly fit closure signature.

 This is most examplified by dictionaries. They always expose (key: Key,
 value: Value) tuples (their Element type). Problem is that 'key' and
 'value' are identifiers that only matter for dictionaries, not for
 dictionary users. It's very important for dictionary users to forget about
 tuples, and the `key` and `value` words:

 // No pollution
 dictionary.map { (name, score) in ... }

>>>
>>> It looks like some people in this mailing list are horrified by this
>>> "request" (not a feature request, but a request that Swift 3 behavior is
>>> restored, actually).
>>>
>>> What could be the reasons for such a bad reaction?
>>>
>>> 1: measurable runtime overhead (slower programs in some cases, without
>>> any obvious way for the developper to notice where is the extra cost)
>>> 2: measurable compiler overhead (slower compilation)
>>> 3: implementation complexity (slower swift progress, technical debt,
>>> etc.)
>>> 4: other?
>>>
>>> I understand 1. We are all fascinated by C++ and Rust "zero-overhead".
>>> If this is the main concern of the community, then we may focus the
>>> discussion of that very precise topic.
>>>
>>> I can live 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution

On 08.06.2017 9:43, Jonathan Hull wrote:
Also, I want to repeat what I said on the other thread.  We should revert to Swift 3 
behavior for this, and then take the time to design the behavior we really want 
(either for 4.1 or 5).  Anything else will cause us to break people’s code twice…


Yes, *just* ignore/revert a number of connected, actively discussed and accepted, 
implemented(partially for some) proposals, freeze the current broken state of 
function types for very long period without any ability in near feature to fix it.


Instead of improvement of the syntax of the problematic parts of code even after 
release (if not possible to suggest a suitable solution before the release). I don't 
think that *improvements* in syntax can break people's code.


Huh..



Thanks,
Jon

On Jun 7, 2017, at 11:50 AM, Gwendal Roué via swift-evolution 
> wrote:



Le 7 juin 2017 à 20:33, Gwendal Roué > a écrit :


For example, take those three functions:

func f(_ closure:(Int, Int) -> ())
func g(_ closure:((Int, Int)) -> ())
func h(_ closure:((a: Int, b: Int)) -> ())

If one can always write (as in Swift 3):

f { (a, b) in ... }
g { (a, b) in ... }
c { (a, b) in ... }

Then one can easily deal with a badly fit closure signature.

This is most examplified by dictionaries. They always expose (key: Key, value: 
Value) tuples (their Element type). Problem is that 'key' and 'value' are 
identifiers that only matter for dictionaries, not for dictionary users. It's very 
important for dictionary users to forget about tuples, and the `key` and `value` 
words:


// No pollution
dictionary.map { (name, score) in ... }


It looks like some people in this mailing list are horrified by this "request" (not 
a feature request, but a request that Swift 3 behavior is restored, actually).


What could be the reasons for such a bad reaction?

1: measurable runtime overhead (slower programs in some cases, without any obvious 
way for the developper to notice where is the extra cost)

2: measurable compiler overhead (slower compilation)
3: implementation complexity (slower swift progress, technical debt, etc.)
4: other?

I understand 1. We are all fascinated by C++ and Rust "zero-overhead". If this is 
the main concern of the community, then we may focus the discussion of that very 
precise topic.


I can live with 2 (just a personal subjective preference)

About 3: I can not tell because I lack the necessary skills.

4: enlighten us!

Gwendal

___
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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Xiaodi Wu via swift-evolution
On Thu, Jun 8, 2017 at 7:53 AM, Vladimir.S  wrote:

> Xiaodi, I'm interested in your opinion, don't you think that *SE-0066* was
> the main proposal that separated (Int,Int)->() and ((Int,Int))->() function
> *types*?
> (https://github.com/apple/swift-evolution/blob/master/propos
> als/0066-standardize-function-type-syntax.md)
>

As far as I can tell, SE-0110 clarified the spelling for a single tuple
argument, SE-0066 standardized the syntax for an argument list, and SE-0029
clarified the behavior of function applications. However, the notion that
(Int, Int) -> () and ((Int, Int)) -> () should be different types,
independent of whether we knew how the two would be spelled, is the
inevitable consequence of distinguishing argument lists from tuples.
According to SE-0029, that change apparently occurred *before Swift 1*, and
so unless I'm mistaken the remainder of this issue has really been
technical debt since that time.

'Proposed solution' section of this proposal clearly separates function
> *type* of one tuple argument and of a list of arguments, no?
>
> It seems like this proposal was NOT fully implemented in Swift 3 or was
> implemented with bugs, or full implementation was delayed, and it just
> should be fully implemented in Swift 4, independent of SE-0110 proposal.
>
> This is why I can't understand, how revisiting of SE-0110 *can help at
> all* ?
>
> OK, let's say we revisited/rejected SE-0110, let's forgot about it for a
> moment. What's next? How the problem with two *separated* types for
> func/closure should be solved when one type is expected and other type is
> provided? Definitely we need new formal proposal for this to discuss in
> details.
>
> Again, even *without* SE-0110 type of (Int,Int)->() should be in Swift 4
> not the same as ((Int,Int))->(). This means that you can't "just sent"
> instance of one type if other type is required.
>
> Vladimir.
>
> On 08.06.2017 6:34, Xiaodi Wu via swift-evolution wrote:
>
>> On Wed, Jun 7, 2017 at 10:12 PM, Stephen Celis > > wrote:
>>
>>
>> > On Jun 7, 2017, at 10:33 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org > wrote:
>> >
>> > However, what I don’t get is why you’d have a mismatch here. Your
>> method `first` accepts a closure, and surely the type it expects should be
>> `((String, Conversation)) -> Bool` instead, since that is the type that the
>> `filter` method expects in the body of your implementation?
>>
>> I must continue to ask for more justification as to why it's _so_
>> valuable to
>> consider "(Int,Int)->()" and "((Int,Int))->()" to be different in
>> _most_ cases.
>> Even in the contrived-described example above, the function may be
>> reusable and
>> the engineer may pass "String" and "Conversation" objects directly in
>> some cases,
>> and this distinction only makes things more difficult and requires
>> cumbersome
>> workarounds.
>>
>> I know you feel that the ship has sailed, and I understand the
>> ambiguities these
>> proposals intended to clarify, but for the most common cases,
>> treating a function
>> that takes a single tuple the same way we treat a function that takes
>> the same
>> number of values that same tuple contains is...really nice, so maybe
>> there's a
>> better way to disambiguate.
>>
>>
>> Again, an argument list was once a tuple: this solution was investigated
>> and "completely abandoned" early in the development of Swift "for a large
>> number of reasons (including inout, default arguments, variadic arguments,
>> labels, etc)". Removal of implicit tuple splatting was outlined in SE-0029.
>> Namely, for a function `foo(_:b:)` called using a tuple `x`:
>>
>>  >A call to foo(x) looks like a call to an overloaded version of foo,
>> both to the compiler and to the human who maintains the code. This is
>> extremely confusing if you don't know the feature exists.
>>  >There are real ambiguities in the syntax, e.g. involving Any arguments
>> and situations where you want to pass a tuple value as a single parameter.
>>  >The current implementation has a ton of implementation bugs - it
>> doesn't work reliably.
>>  >The current implementation adds complexity to the type checker, slowing
>> it down and adding maintenance burden.
>>  >The current implementation doesn't work the way we would want a tuple
>> splat operation to work.
>>
>> ...
>>
>>  >The root problem here is that we use exactly the same syntax for both
>> forms of function application. If the two forms were differentiated (an
>> option considered in “alternatives considered” below) then some of these
>> problems would be defined away.
>>
>> However,
>>
>>  >[A]ctually designing this feature would be a non-trivial effort...
>>  >We don't have an obvious sigil to use. "prefix-star" should be left
>> unused for now in case we want to use it to refer to memory-related
>> 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution

On 08.06.2017 12:17, Víctor Pimentel Rodríguez via swift-evolution wrote:
On Thu, Jun 8, 2017 at 5:15 AM, Susan Cheng via swift-evolution 
> wrote:


Just a thought

if parentheses is important, why the tuples are not?


This is stated on the proposal (and not in previous proposals):

https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md

  *

We understand that this may be a departure from the current convention that 
a set
of parentheses enclosing a single object are considered semantically 
meaningless,
but it is the most natural way to differentiate between the two situations
described above and would be a clearly-delineated one-time-only exception.





This proposal marks a one-time-only exception, to differentiate the parenthesis 
needed to enclose a list of closure parameters and the parenthesis needed for tuples. 
That's adding an exception for implementing a regression.


The more I think about it, the more I hate* this proposal.

* Well, not _hate_, let's say slightly dislike :P


Please look here:
https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md

into "Proposed solution" section:

Parentheses will be required in function types. Examples:

Int -> Int   // error
(Int) -> Int // function from Int to Int
((Int)) -> Int   // also function from Int to Int

Int, Int -> Int  // error
(Int, Int) -> Int// function from Int and Int to Int
((Int, Int)) -> Int  // function from tuple (Int, Int) to Int

let f: () -> Int // function with no parameters
let g: (()) -> Int   // function taking a single () parameter
let h: ((())) -> Int // function taking a single () parameter

f();   g(()); h(())  // correct
f(()); g();   h()// errors

Do you also hate* SE-0066?



--
Víctor Pimentel


___
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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Vladimir.S via swift-evolution
Xiaodi, I'm interested in your opinion, don't you think that *SE-0066* was the main 
proposal that separated (Int,Int)->() and ((Int,Int))->() function *types*?

(https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md)

'Proposed solution' section of this proposal clearly separates function *type* of one 
tuple argument and of a list of arguments, no?


It seems like this proposal was NOT fully implemented in Swift 3 or was implemented 
with bugs, or full implementation was delayed, and it just should be fully 
implemented in Swift 4, independent of SE-0110 proposal.


This is why I can't understand, how revisiting of SE-0110 *can help at all* ?

OK, let's say we revisited/rejected SE-0110, let's forgot about it for a moment. 
What's next? How the problem with two *separated* types for func/closure should be 
solved when one type is expected and other type is provided? Definitely we need new 
formal proposal for this to discuss in details.


Again, even *without* SE-0110 type of (Int,Int)->() should be in Swift 4 not the same 
as ((Int,Int))->(). This means that you can't "just sent" instance of one type if 
other type is required.


Vladimir.

On 08.06.2017 6:34, Xiaodi Wu via swift-evolution wrote:
On Wed, Jun 7, 2017 at 10:12 PM, Stephen Celis > wrote:


> On Jun 7, 2017, at 10:33 PM, Xiaodi Wu via swift-evolution 
> wrote:
>
> However, what I don’t get is why you’d have a mismatch here. Your method 
`first` accepts a closure, and surely the type it expects should be `((String, 
Conversation)) -> Bool` instead, since that is the type that the `filter` method 
expects in the body of your implementation?

I must continue to ask for more justification as to why it's _so_ valuable 
to
consider "(Int,Int)->()" and "((Int,Int))->()" to be different in _most_ 
cases.
Even in the contrived-described example above, the function may be reusable 
and
the engineer may pass "String" and "Conversation" objects directly in some 
cases,
and this distinction only makes things more difficult and requires 
cumbersome
workarounds.

I know you feel that the ship has sailed, and I understand the ambiguities 
these
proposals intended to clarify, but for the most common cases, treating a 
function
that takes a single tuple the same way we treat a function that takes the 
same
number of values that same tuple contains is...really nice, so maybe 
there's a
better way to disambiguate.


Again, an argument list was once a tuple: this solution was investigated and 
"completely abandoned" early in the development of Swift "for a large number of 
reasons (including inout, default arguments, variadic arguments, labels, etc)". 
Removal of implicit tuple splatting was outlined in SE-0029. Namely, for a function 
`foo(_:b:)` called using a tuple `x`:


 >A call to foo(x) looks like a call to an overloaded version of foo, both to the 
compiler and to the human who maintains the code. This is extremely confusing if you 
don't know the feature exists.
 >There are real ambiguities in the syntax, e.g. involving Any arguments and 
situations where you want to pass a tuple value as a single parameter.

 >The current implementation has a ton of implementation bugs - it doesn't work 
reliably.
 >The current implementation adds complexity to the type checker, slowing it down and 
adding maintenance burden.
 >The current implementation doesn't work the way we would want a tuple splat 
operation to work.


...

 >The root problem here is that we use exactly the same syntax for both forms of 
function application. If the two forms were differentiated (an option considered in 
“alternatives considered” below) then some of these problems would be defined away.


However,

 >[A]ctually designing this feature would be a non-trivial effort...
 >We don't have an obvious sigil to use. "prefix-star" should be left unused for now 
in case we want to use it to refer to memory-related operations in the future.
 >Making the tuple splat operation great requires more than just fixing the syntactic 
ambiguities we have, it would require re-evaluating the semantics of the operation 
(e.g. in light of parameter labels, varargs and other features).


The removal of tuple splatting was approved during Swift *2* Evolution; it so happens 
that one particular segment of the feature was not excised until SE-0110, but the 
writing was on the wall, so to speak, for 18 months.


I'll work with whatever final solution the Swift team comes up with, but in 
the
meantime I'm not going to shy away from reacting to regressions.

I've referred to these regressions as "ergonomic" in the past, but it's more
about expressiveness. Swift 3 (and earlier) syntax allowed for functional,
point-free expression that could amount to very succinct, 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Víctor Pimentel Rodríguez via swift-evolution
On Thu, Jun 8, 2017 at 5:15 AM, Susan Cheng via swift-evolution <
swift-evolution@swift.org> wrote:

> Just a thought
>
> if parentheses is important, why the tuples are not?
>

This is stated on the proposal (and not in previous proposals):

https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md

   -

   We understand that this may be a departure from the current convention
   that a set of parentheses enclosing a single object are considered
   semantically meaningless, but it is the most natural way to differentiate
   between the two situations described above and would be a
   clearly-delineated one-time-only exception.

This
proposal marks a one-time-only exception, to differentiate the parenthesis
needed to enclose a list of closure parameters and the parenthesis needed
for tuples. That's adding an exception for implementing a regression.

The more I think about it, the more I hate* this proposal.

* Well, not _hate_, let's say slightly dislike :P

-- 
Víctor Pimentel
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Jonathan Hull via swift-evolution
Also, I want to repeat what I said on the other thread.  We should revert to 
Swift 3 behavior for this, and then take the time to design the behavior we 
really want (either for 4.1 or 5).  Anything else will cause us to break 
people’s code twice…

Thanks,
Jon

> On Jun 7, 2017, at 11:50 AM, Gwendal Roué via swift-evolution 
>  wrote:
> 
> 
>> Le 7 juin 2017 à 20:33, Gwendal Roué > > a écrit :
>> 
>> For example, take those three functions:
>> 
>>  func f(_ closure:(Int, Int) -> ())
>>  func g(_ closure:((Int, Int)) -> ())
>>  func h(_ closure:((a: Int, b: Int)) -> ())
>> 
>> If one can always write (as in Swift 3):
>> 
>>  f { (a, b) in ... }
>>  g { (a, b) in ... }
>>  c { (a, b) in ... }
>> 
>> Then one can easily deal with a badly fit closure signature.
>> 
>> This is most examplified by dictionaries. They always expose (key: Key, 
>> value: Value) tuples (their Element type). Problem is that 'key' and 'value' 
>> are identifiers that only matter for dictionaries, not for dictionary users. 
>> It's very important for dictionary users to forget about tuples, and the 
>> `key` and `value` words:
>> 
>>  // No pollution
>>  dictionary.map { (name, score) in ... }
> 
> It looks like some people in this mailing list are horrified by this 
> "request" (not a feature request, but a request that Swift 3 behavior is 
> restored, actually).
> 
> What could be the reasons for such a bad reaction?
> 
> 1: measurable runtime overhead (slower programs in some cases, without any 
> obvious way for the developper to notice where is the extra cost)
> 2: measurable compiler overhead (slower compilation)
> 3: implementation complexity (slower swift progress, technical debt, etc.)
> 4: other?
> 
> I understand 1. We are all fascinated by C++ and Rust "zero-overhead". If 
> this is the main concern of the community, then we may focus the discussion 
> of that very precise topic.
> 
> I can live with 2 (just a personal subjective preference)
> 
> About 3: I can not tell because I lack the necessary skills.
> 
> 4: enlighten us!
> 
> Gwendal
> 
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-08 Thread Jonathan Hull via swift-evolution

> On Jun 7, 2017, at 11:33 AM, Gwendal Roué via swift-evolution 
>  wrote:
> 
> So far, the answer to the ergonomics regression reports have been much too 
> often negative. I wish ergonomics had better support in the community. Very 
> few regular developers talk here, unfortunately.

Yes, I unfortunately agree.  The best term I have heard to describe this list 
is “Combative”.

I wish actual user experience / human factors was a greater consideration here, 
and that often requires little touches that are immediately dismissed from this 
list as being not-significant/important enough.  But those little touches add 
up to make the overall experience… and our experience has been suffering as a 
result.

I don’t mean to offend, and I feel like I am learning a lot from everyone here 
(I am an experienced mac/iOS developer, but I mainly work as a designer and 
teacher).  I just really wish the list was more open to a range of voices. 

Thanks,
Jon

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
that makes sense to me ;P

2017-06-08 12:07 GMT+08:00 Gwendal Roué :

> Le 8 juin 2017 à 05:15, Susan Cheng via swift-evolution <
> swift-evolution@swift.org> a écrit :
>
> Just a thought
>
> if parentheses is important, why the tuples are not?
>
> var tuple1: (Int, Int) = (0, 0)
> var tuple2: Int, Int = (0, 0)
>
> type(of: tuple1) == type(of: tuple2)// true
>
> var void: ((())) = ()
>
> type(of: void) == type(of: Void())  // true
>
>
> I think is is because Swift doesn't have tuples with a single value: those
> parenthesis are just parenthesis around an expression:
>
> let a = 1 + 2
> let b = (1 + 2)
> let c = (1 + 2) * 3
> let d = ((1 + 2)) * 3
>
> Many languages behave like that, Swift is no exception.
>
> It also allows some fancy/legacy/foreign programming styles :-)
>
> // C-style if
> if (a && b) {
> ...
> }
> // "return function"
> return(a && b)
>
> Languages that have single-valued tuples need a special syntax so that
> they are distinguished from parenthesised expressions. In Python, this is a
> trailing comma:
>
> 1# 1
> (1)  # 1
> (1,) # (1,)
>
> Swift currently disallows trailing commas inside parenthesis.
>
> Gwendal
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution
> Le 8 juin 2017 à 05:15, Susan Cheng via swift-evolution 
>  a écrit :
> 
> Just a thought
> 
> if parentheses is important, why the tuples are not?
> 
> var tuple1: (Int, Int) = (0, 0)
> var tuple2: Int, Int = (0, 0)
> 
> type(of: tuple1) == type(of: tuple2)// true
> 
> var void: ((())) = ()
> 
> type(of: void) == type(of: Void())  // true

I think is is because Swift doesn't have tuples with a single value: those 
parenthesis are just parenthesis around an expression:

let a = 1 + 2
let b = (1 + 2)
let c = (1 + 2) * 3
let d = ((1 + 2)) * 3

Many languages behave like that, Swift is no exception.

It also allows some fancy/legacy/foreign programming styles :-)

// C-style if
if (a && b) {
...
}
// "return function"
return(a && b)

Languages that have single-valued tuples need a special syntax so that they are 
distinguished from parenthesised expressions. In Python, this is a trailing 
comma:

1# 1
(1)  # 1
(1,) # (1,)

Swift currently disallows trailing commas inside parenthesis.

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
if it's necessary to distinct argument list and tuple, what about the enum?


enum Foo {

case tuple(a: Int, b: Int)

}


let tuple = Foo.tuple((1, 2))


if case let .tuple(a, b) = tuple {



(a, b)//  (1, 2)

}


if case let .tuple(tuple) = tuple {



tuple//  (1, 2)

}




2017-06-08 11:36 GMT+08:00 Xiaodi Wu :

> On Wed, Jun 7, 2017 at 10:15 PM, Susan Cheng via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Just a thought
>>
>> if parentheses is important, why the tuples are not?
>>
>
> It is not parentheses that are important; it is the distinction between an
> argument list and a tuple. They both happen to be written with parentheses.
>
> var tuple1: (Int, Int) = (0, 0)
>>
>> var tuple2: Int, Int = (0, 0)
>>
>>
>> type(of: tuple1) == type(of: tuple2)// true
>>
>>
>> var void: ((())) = ()
>>
>>
>> type(of: void) == type(of: Void())  // true
>>
>>
>> 2017-06-07 10:15 GMT+08:00 Susan Cheng :
>>
>>> Introduction
>>>
>>> Because the painful of SE-0110, here is a proposal to clarify the tuple
>>> syntax.
>>>
>>> Proposed solution
>>> 1. single element tuple always be flattened
>>>
>>> let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>>>
>>>
>>> let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
>>>
>>> 2. function arguments list also consider as a tuple, which means the
>>> function that accept a single tuple should always be flattened.
>>>
>>> let fn1: (Int, Int) -> Void = { _, _ in }
>>>
>>>
>>> let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
>>>
>>> let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
>>> arguments
>>>
>>> let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
>>> arguments
>>>
>>>
>>
>> ___
>> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 10:15 PM, Susan Cheng via swift-evolution <
swift-evolution@swift.org> wrote:

> Just a thought
>
> if parentheses is important, why the tuples are not?
>

It is not parentheses that are important; it is the distinction between an
argument list and a tuple. They both happen to be written with parentheses.

var tuple1: (Int, Int) = (0, 0)
>
> var tuple2: Int, Int = (0, 0)
>
>
> type(of: tuple1) == type(of: tuple2)// true
>
>
> var void: ((())) = ()
>
>
> type(of: void) == type(of: Void())  // true
>
>
> 2017-06-07 10:15 GMT+08:00 Susan Cheng :
>
>> Introduction
>>
>> Because the painful of SE-0110, here is a proposal to clarify the tuple
>> syntax.
>>
>> Proposed solution
>> 1. single element tuple always be flattened
>>
>> let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>>
>>
>> let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
>>
>> 2. function arguments list also consider as a tuple, which means the
>> function that accept a single tuple should always be flattened.
>>
>> let fn1: (Int, Int) -> Void = { _, _ in }
>>
>>
>> let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
>>
>> let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
>> arguments
>>
>> let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
>> arguments
>>
>>
>
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 10:12 PM, Stephen Celis 
wrote:

> > On Jun 7, 2017, at 10:33 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > However, what I don’t get is why you’d have a mismatch here. Your method
> `first` accepts a closure, and surely the type it expects should be
> `((String, Conversation)) -> Bool` instead, since that is the type that the
> `filter` method expects in the body of your implementation?
>
> I must continue to ask for more justification as to why it's _so_ valuable
> to consider "(Int,Int)->()" and "((Int,Int))->()" to be different in _most_
> cases. Even in the contrived-described example above, the function may be
> reusable and the engineer may pass "String" and "Conversation" objects
> directly in some cases, and this distinction only makes things more
> difficult and requires cumbersome workarounds.
>
> I know you feel that the ship has sailed, and I understand the ambiguities
> these proposals intended to clarify, but for the most common cases,
> treating a function that takes a single tuple the same way we treat a
> function that takes the same number of values that same tuple contains
> is...really nice, so maybe there's a better way to disambiguate.
>

Again, an argument list was once a tuple: this solution was investigated
and "completely abandoned" early in the development of Swift "for a large
number of reasons (including inout, default arguments, variadic arguments,
labels, etc)". Removal of implicit tuple splatting was outlined in SE-0029.
Namely, for a function `foo(_:b:)` called using a tuple `x`:

>A call to foo(x) looks like a call to an overloaded version of foo, both
to the compiler and to the human who maintains the code. This is extremely
confusing if you don't know the feature exists.
>There are real ambiguities in the syntax, e.g. involving Any arguments and
situations where you want to pass a tuple value as a single parameter.
>The current implementation has a ton of implementation bugs - it doesn't
work reliably.
>The current implementation adds complexity to the type checker, slowing it
down and adding maintenance burden.
>The current implementation doesn't work the way we would want a tuple
splat operation to work.

...

>The root problem here is that we use exactly the same syntax for both
forms of function application. If the two forms were differentiated (an
option considered in “alternatives considered” below) then some of these
problems would be defined away.

However,

>[A]ctually designing this feature would be a non-trivial effort...
>We don't have an obvious sigil to use. "prefix-star" should be left unused
for now in case we want to use it to refer to memory-related operations in
the future.
>Making the tuple splat operation great requires more than just fixing the
syntactic ambiguities we have, it would require re-evaluating the semantics
of the operation (e.g. in light of parameter labels, varargs and other
features).

The removal of tuple splatting was approved during Swift *2* Evolution; it
so happens that one particular segment of the feature was not excised until
SE-0110, but the writing was on the wall, so to speak, for 18 months.

I'll work with whatever final solution the Swift team comes up with, but in
> the meantime I'm not going to shy away from reacting to regressions.
>
> I've referred to these regressions as "ergonomic" in the past, but it's
> more about expressiveness. Swift 3 (and earlier) syntax allowed for
> functional, point-free expression that could amount to very succinct,
> readable code. The code Swift 4 requires is harder to read and harder to
> maintain.
>
> Stephen
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
Just a thought

if parentheses is important, why the tuples are not?


var tuple1: (Int, Int) = (0, 0)

var tuple2: Int, Int = (0, 0)


type(of: tuple1) == type(of: tuple2)// true


var void: ((())) = ()


type(of: void) == type(of: Void())  // true


2017-06-07 10:15 GMT+08:00 Susan Cheng :

> Introduction
>
> Because the painful of SE-0110, here is a proposal to clarify the tuple
> syntax.
>
> Proposed solution
> 1. single element tuple always be flattened
>
> let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>
>
> let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
>
> 2. function arguments list also consider as a tuple, which means the
> function that accept a single tuple should always be flattened.
>
> let fn1: (Int, Int) -> Void = { _, _ in }
>
>
> let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
>
> let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
> arguments
>
> let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
> arguments
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Stephen Celis via swift-evolution
> On Jun 7, 2017, at 10:33 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> However, what I don’t get is why you’d have a mismatch here. Your method 
> `first` accepts a closure, and surely the type it expects should be 
> `((String, Conversation)) -> Bool` instead, since that is the type that the 
> `filter` method expects in the body of your implementation?

I must continue to ask for more justification as to why it's _so_ valuable to 
consider "(Int,Int)->()" and "((Int,Int))->()" to be different in _most_ cases. 
Even in the contrived-described example above, the function may be reusable and 
the engineer may pass "String" and "Conversation" objects directly in some 
cases, and this distinction only makes things more difficult and requires 
cumbersome workarounds.

I know you feel that the ship has sailed, and I understand the ambiguities 
these proposals intended to clarify, but for the most common cases, treating a 
function that takes a single tuple the same way we treat a function that takes 
the same number of values that same tuple contains is...really nice, so maybe 
there's a better way to disambiguate.

I'll work with whatever final solution the Swift team comes up with, but in the 
meantime I'm not going to shy away from reacting to regressions.

I've referred to these regressions as "ergonomic" in the past, but it's more 
about expressiveness. Swift 3 (and earlier) syntax allowed for functional, 
point-free expression that could amount to very succinct, readable code. The 
code Swift 4 requires is harder to read and harder to maintain.

Stephen

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 19:15 Víctor Pimentel Rodríguez 
wrote:

> On 7 Jun 2017, at 21:29, Xiaodi Wu  wrote:
>
>
> SE-0110 may be an obvious extension of the proposed goal, but it is clear
>> that it has been implemented in Swift 4, and that the consequences are
>> derived of those changesets.
>>
>> Those "unwanted" consequences can be reverted by temporarily reverting
>> SE-0110, without touching any other previous proposal.
>>
>> In no place I see Gwendal asking for full reversal of 5 proposals. He is
>> just voicing something that a lot of app developers and library maintainers
>> are not going to understand in September.
>>
>> For example, you can see all the changes needed in RXSwift so that it
>> compiles to Swift 4:
>>
>> https://github.com/ReactiveX/RxSwift/pull/1282/commits/
>> 915e00fa6d1e59d58cd8c38dd6dc83765fc67fe4
>>
>> I would not want to migrate to Swift 4 an app using such framework.
>>
>> I asked you in my first reply to you, is your view that the distinction
>> itself between (Int, Int) -> Int and ((Int, Int)) -> Int is problematic? If
>> so, this is a very different discussion from seeking solutions to mitigate
>> particular ergonomic issues that arise from the change. However, you have
>> not answered the question.
>>
>>
>> As far as I can see, the bigger usability regressions are caused when
>> using generics, specially in collections and functional utilities. When you
>> specify that type with a tuple, as in Dictionary, then all the related
>> methods start receiving closures receiving tuples.
>>
>> Notice that allowing some syntactic sugar on the call site of those
>> closures may not be enough, since you may have stored or passed a closure
>> for customization purposes.
>>
>
> Can you illustrate this with an example? I’m not sure I understand what
> you’re getting at here.
>
>
> Sure. Let's say you want to filter some elements from a dictionary, and
> you have this valid Swift 3 code:
>
> let conversationsById: [String: Conversation]
> let unreadConversations = conversationsById.filter { $1.isUnread }
>
> Or:
>
> let unreadConversations = conversationsById.filter { id, c in
> return !id.isEmpty && c.isUnread
> }
>
> Neither of these expressions are permitted in Swift 4, but some syntactic
> sugar can be added to allowing it again without the need of full tuple
> splatting.
>

Right.

However, if for some reason you want to pass around a filter closure, you
> will still have mismatch types:
>
> func first(passing filter: (String, Conversation) -> Bool) ->
> Conversation? {
> return conversationsById.filter(filter).first?.value
> }
>

> This example is simple and useless and contrived, but it gets even worse
> when you take generics into account to catch any type of closure.
>

I’m not going to raise any issues over how realistic the scenario might be.
It's for answering a question, after all.

However, what I don’t get is why you’d have a mismatch here. Your method
`first` accepts a closure, and surely the type it expects should be
`((String, Conversation)) -> Bool` instead, since that is the type that the
`filter` method expects in the body of your implementation?

Certainly, there are scenarios not possible (or at least, very difficult)
without tuple splatting, but that’s straight-up an argument for tuple
splatting. That's, IMO, an unnecessary argument, since the usefulness of
the feature has never been in question, only the resources to design and
implement.

This behavior is so hurtful to functional style programming, that I think
>> either SE-0110 should be reverted, or alternatives like this Susan proposal
>> should be implemented.
>>
>
> To be clear, what you and Gwendal are objecting to is the loss of tuple
> splatting, is it not? Again, SE-0110 is only the final piece; SE-0029 is
> what removed implicit tuple splatting. As that proposal said, a properly
> designed explicit tuple splatting can be considered if there’s demand, and
> it was understood that removing this functionality would be a regression
> and nonetheless the decision for removal was still deliberately undertaken.
> Re-reading that proposal, the rationale was that it never worked correctly
> to begin with, and the barrier for bringing it back is that it requires
> considerable effort to design and implement the feature correctly.
>
> I'm sorry if there has been any disrespect for my part, I appreciate what
> you all do here. But sometimes it's a bit frustrating having to explain why
> something that seems obvious to us is not obvious to others.
>
> I think that you have a bigger picture from the Swift Evolution point, but
> the thing is that Swift users like me doesn't have that context, and we are
> baffled when we encounter that some pretty simple code turns into a weird
> thing in a migration. I have linked to several real examples out there, and
> it seems to be a popular opinion. Nevertheless, it was Tony Parker's mail
> the one that kindled this 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Víctor Pimentel Rodríguez via swift-evolution
On 7 Jun 2017, at 21:29, Xiaodi Wu  wrote:


SE-0110 may be an obvious extension of the proposed goal, but it is clear
> that it has been implemented in Swift 4, and that the consequences are
> derived of those changesets.
>
> Those "unwanted" consequences can be reverted by temporarily reverting
> SE-0110, without touching any other previous proposal.
>
> In no place I see Gwendal asking for full reversal of 5 proposals. He is
> just voicing something that a lot of app developers and library maintainers
> are not going to understand in September.
>
> For example, you can see all the changes needed in RXSwift so that it
> compiles to Swift 4:
>
> https://github.com/ReactiveX/RxSwift/pull/1282/commits/915e0
> 0fa6d1e59d58cd8c38dd6dc83765fc67fe4
>
> I would not want to migrate to Swift 4 an app using such framework.
>
> I asked you in my first reply to you, is your view that the distinction
> itself between (Int, Int) -> Int and ((Int, Int)) -> Int is problematic? If
> so, this is a very different discussion from seeking solutions to mitigate
> particular ergonomic issues that arise from the change. However, you have
> not answered the question.
>
>
> As far as I can see, the bigger usability regressions are caused when
> using generics, specially in collections and functional utilities. When you
> specify that type with a tuple, as in Dictionary, then all the related
> methods start receiving closures receiving tuples.
>
> Notice that allowing some syntactic sugar on the call site of those
> closures may not be enough, since you may have stored or passed a closure
> for customization purposes.
>

Can you illustrate this with an example? I’m not sure I understand what
you’re getting at here.


Sure. Let's say you want to filter some elements from a dictionary, and you
have this valid Swift 3 code:

let conversationsById: [String: Conversation]
let unreadConversations = conversationsById.filter { $1.isUnread }

Or:

let unreadConversations = conversationsById.filter { id, c in
return !id.isEmpty && c.isUnread
}

Neither of these expressions are permitted in Swift 4, but some syntactic
sugar can be added to allowing it again without the need of full tuple
splatting.

However, if for some reason you want to pass around a filter closure, you
will still have mismatch types:

func first(passing filter: (String, Conversation) -> Bool) -> Conversation?
{
return conversationsById.filter(filter).first?.value
}

This example is simple and useless and contrived, but it gets even worse
when you take generics into account to catch any type of closure.

This behavior is so hurtful to functional style programming, that I think
> either SE-0110 should be reverted, or alternatives like this Susan proposal
> should be implemented.
>

To be clear, what you and Gwendal are objecting to is the loss of tuple
splatting, is it not? Again, SE-0110 is only the final piece; SE-0029 is
what removed implicit tuple splatting. As that proposal said, a properly
designed explicit tuple splatting can be considered if there’s demand, and
it was understood that removing this functionality would be a regression
and nonetheless the decision for removal was still deliberately undertaken.
Re-reading that proposal, the rationale was that it never worked correctly
to begin with, and the barrier for bringing it back is that it requires
considerable effort to design and implement the feature correctly.

I'm sorry if there has been any disrespect for my part, I appreciate what
you all do here. But sometimes it's a bit frustrating having to explain why
something that seems obvious to us is not obvious to others.

I think that you have a bigger picture from the Swift Evolution point, but
the thing is that Swift users like me doesn't have that context, and we are
baffled when we encounter that some pretty simple code turns into a weird
thing in a migration. I have linked to several real examples out there, and
it seems to be a popular opinion. Nevertheless, it was Tony Parker's mail
the one that kindled this discussion with a really simple question.

It may be the last piece, but it is the piece that impacted simple code the
most, or at least the one that had the most unexpected consequences.
Certainly that proposal does not contain nearly enough code examples or
goes deeply enough. And this is subjective, but for me this isn't true:
"Minor changes to user code may be required if this proposal is accepted."

The fact that it affects even the standard library shows how hurtful
removing this feature is. It's not a nice-to-have feature or a
somewhat-useful feature, it's that right now it's very difficult to model
something as essential as Dictionary with a nice-to-use API. So lots of
other custom types will suffer too.

If we all agree that this is a loss of ergonomics, then the Core Team have
several options for Swift 4:

1. Do nothing.
2. Revert SE-0110 related changes.
3. Add a complex tuple-splatting feature.
4. Add some 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Vladimir.S via swift-evolution

On 07.06.2017 21:33, Gwendal Roué wrote:


Le 7 juin 2017 à 17:15, Vladimir.S > a 
écrit :


On 07.06.2017 16:20, Gwendal Roué wrote:
Le 7 juin 2017 à 15:11, Xiaodi Wu  > a écrit :


While SE-0025 was generally regarded as unfortunate, the thousands of emails that 
followed relitigating it were much, much worse.


The removal of implicit tuple splatting, which is *not* SE-0110, was approved on 
the understanding that it would be a regression until explicit tuple splatting is 
introduced. This tradeoff was considered and approved. It’s clear that you 
disagree, but that is not grounds to divert a necessary discussion on mitigating 
SE-0110 into relitigating something else.

Push me out if you want, but will you push out those blatant wounds out as well?
Example 1
-return columns.index { (column, _) in column.lowercased() == 
lowercaseName }
+return columns.index { $0.0.lowercased() == lowercaseName }


Why not
columns.index { (arg: (column: String, _: Int)) in arg.column.lowercased() == 
lowercaseName }

?


It would works, but it's less than ideal: the `args` name has no meaning. We have an 
extra type declaration instead of type inference. 


Yes, as I said below, it's clearly 'less than ideal', but I do believe this variant 
is much better than what you shown as regression example. That was my main point.


As for 'arg' name.. well.. naming is very hard task ;-) I didn't think about name in 
this case, probably 'arg' should be 'column' and current 'column' should be just 
'name', if I understand correctly:
columns.index { (column: (name: String, _: Int)) in column.name.lowercased() == 
lowercaseName }



Btw, I forgot to mention another one good(IMO) suggestion for tuple argument 
destructuring syntax in closure:


* allow type inference for tuple parts in already allowed syntax i.e. :
columns.index { (column: (name, _)) in column.name.lowercased() == 
lowercaseName }

I even feel like this one can be the best candidate *for now* as it just relaxes 
requirements for type annotation, allows type inference, that seems very naturally 
for closures. Similar like we can omit type for arguments in argument list, but just 
for tuple parts. This could be just additive sugar for closures that will help to 
migrate to Swift 4 with *less* pain. Then we'll have an ability to discuss best 
solution for tuple argument deconstruction in details in separate proposal, after 
Swift4 is released.


> It's much longer. The clarity is
> tremendously reduced.

I just can't agree with this. IMO it is slightly longer, and clarity is slightly 
reduced.




- return columns.index { (column, _) in column.lowercased() == lowercaseName }
+ return columns.index { (arg: (column: String, _)) in arg.column.lowercased() == 
lowercaseName }


Yes, I understand that first syntax short and not verbose, but the alternative you 
provided IMHO much worse than explicit type declaration in closure.


It's not an "alternative": it's Swift 3.

Maybe you did already profit from it, but did not notice.



Sorry, I don't understand.
I assume you had this code for Swift 3:
return columns.index { (column, _) in column.lowercased() == lowercaseName }
and you need to convert it to Swift 4, so you are saying "look how this is 
ugly":
return columns.index { $0.0.lowercased() == lowercaseName }
and I'm saying "we can instead in Swift 4 have this":
return columns.index { (arg: (column: String, _)) in arg.column.lowercased() ==
 lowercaseName }
which is IMO much better *and* will compile in Swift 3 also.




Example 2 :
-.map { (mappedColumn, baseColumn) -> (Int, String) in
+.map { (pair) -> (Int, String) in
+let mappedColumn = pair.key
+let baseColumn = pair.value


Can't compile something like this even in Swift 3, could you provide a small code 
snippet for this?


Sure:

 letmapping: [String: String] = ...
 mapping.map { (mappedColumn, baseColumn) -> (Int, String) in ... }



Thank you, yes, here is the same:

let mapping: [String: String] = ["1":"2", "3":"4"]
let _ = mapping.map { (item: (mappedColumn: String, baseColumn: String)) -> (Int, 
String) in (0, item.baseColumn) }



Example 3 :
-.map { (table, columns) in 
"\(table)(\(columns.sorted().joined(separator: ", ")))" }

+.map { "\($0.key)(\($0.value.sorted().joined(separator: ", 
")))" }


Same, why not

.map { (arg: (table: String, columns: [String])) in 
"\(arg.table)(\(arg.columns.sorted().joined(separator: ", ")))" }


Same answer: the extra `args` works, but we still have an ergonomics regression from 
Swift 3.


Agree. We have some ergonomics regression in this case. But for now, it is IMO the 
best solution we have to port such Swift 3 code to Swift 4. Let's wait what core team 
will decide about this.





Example 4 :
-dictionary.first { 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 14:33 Gwendal Roué via swift-evolution <
swift-evolution@swift.org> wrote:

> Le 7 juin 2017 à 17:15, Vladimir.S  a écrit :
>
> On 07.06.2017 16:20, Gwendal Roué wrote:
>
> Le 7 juin 2017 à 15:11, Xiaodi Wu  mailto:xiaodi...@gmail.com >> a écrit :
>
> While SE-0025 was generally regarded as unfortunate, the thousands of
> emails that followed relitigating it were much, much worse.
>
> The removal of implicit tuple splatting, which is *not* SE-0110, was
> approved on the understanding that it would be a regression until explicit
> tuple splatting is introduced. This tradeoff was considered and approved.
> It’s clear that you disagree, but that is not grounds to divert a necessary
> discussion on mitigating SE-0110 into relitigating something else.
>
> Push me out if you want, but will you push out those blatant wounds out as
> well?
> Example 1
> -return columns.index { (column, _) in column.lowercased() ==
> lowercaseName }
> +return columns.index { $0.0.lowercased() == lowercaseName }
>
>
> Why not
> columns.index { (arg: (column: String, _: Int)) in arg.column.lowercased()
> == lowercaseName }
> ?
>
>
> It would works, but it's less than ideal: the `args` name has no meaning.
> We have an extra type declaration instead of type inference. It's much
> longer. The clarity is tremendously reduced.
>
> - return columns.index { (column, _) in column.lowercased() ==
> lowercaseName }
> + return columns.index { (arg: (column: String, _)) in
> arg.column.lowercased() == lowercaseName }
>
> Yes, I understand that first syntax short and not verbose, but the
> alternative you provided IMHO much worse than explicit type declaration in
> closure.
>
>
> It's not an "alternative": it's Swift 3.
>
> Maybe you did already profit from it, but did not notice.
>
>
> Example 2 :
> -.map { (mappedColumn, baseColumn) -> (Int, String) in
> +.map { (pair) -> (Int, String) in
> +let mappedColumn = pair.key
> +let baseColumn = pair.value
>
>
> Can't compile something like this even in Swift 3, could you provide a
> small code snippet for this?
>
>
> Sure:
>
> let mapping: [String: String] = ...
> mapping.map { (mappedColumn, baseColumn) -> (Int, String) in ... }
>
> Example 3 :
> -.map { (table, columns) in
> "\(table)(\(columns.sorted().joined(separator: ", ")))" }
> +.map { "\($0.key)(\($0.value.sorted().joined(separator:
> ", ")))" }
>
>
> Same, why not
>
> .map { (arg: (table: String, columns: [String])) in
> "\(arg.table)(\(arg.columns.sorted().joined(separator: ", ")))" }
>
>
> Same answer: the extra `args` works, but we still have an ergonomics
> regression from Swift 3.
>
> Example 4 :
> -dictionary.first { (column, value) in column.lowercased()
> == orderedColumn.lowercased() }
> +dictionary.first { $0.key.lowercased() ==
> orderedColumn.lowercased() }
>
>
> Same.
>
>
> Indeed.
>
>
> See also messages from Stephen Cellis, who shows how other kinds of
> developer code has lost expressivity and clarity with those changes that
> have been "considered and approved".
>
>
> Gwendal, no one saying that new syntax is better, that it is good thing
> that we lost the short syntax for tuple argumment deconstructions in
> closures.
>
>
> Good to hear :-)
>
> But there is just no easy/obvious way to keep that syntax in Swift 4. The
> problem can't be solved just by not implementing SE-0110, as in Swift4 we
> should have two separate function types: one that takes single tuple
> argument and second that accepts a list of arguments, i.e. (Int,Int)->()
> and ((Int,Int))->() should be two different types now.
>
>
> Of course I understand that.
>
> I expect the compiler to perform the expected conversions for ergonomics'
> sake.
>
> I can understand that this sugar could be added *after* current problems
> which are not related to ergonomics are solved. I just want to make it
> clear that there is an ergonomics problem *now*, and that solving it should
> have a very high priority.
>

If this was the point you wished to make, then there isn’t any
disagreement, I don’t think. We *all* can obviously agree that there is a
loss in ergonomics due to SE-0110.

This is not just SE-0110, this is also SE-0066, so, to be correct, you
> should propose to revisit it also.
>
> Please look here:
>
> func foo(_ x: Int, _ y: Int) {} // type(of: foo) should be (Int, Int)->()
> func bar(_ x (Int, Int)) {} // type(of: bar) should be ((Int, Int))->()
>
> The above is described in SE-0066. Then, you have a closure constants:
>
> var fooClosure = {(x: Int, y: Int) in }
> var barClosure = {(x: (Int, Int)) in }
>
> what should be types of these closures? Obvious the same: (Int,Int)->()
> and ((Int,Int))->() respectively.
>
>
> I guess you mean, not the same: (Int, Int) -> () vs. ((Int, Int)) -> ().
>
> Then you have a func that accepts 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 14:13 Víctor Pimentel Rodríguez 
wrote:

>
> On 7 Jun 2017, at 18:10, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Wed, Jun 7, 2017 at 10:03 Gwendal Roué  wrote:
>
>> Le 7 juin 2017 à 15:52, Xiaodi Wu  a écrit :
>>
>> Let’s clarify: you just wrote that you have problems with SE-0029,
>> SE-0066, SE-0110, and “before,” did you not?
>>
>>
>> WTF? No I did not (citation below)!
>>
>> Le 7 juin 2017 à 15:02, Gwendal Roué  a écrit :
>>
>> Le 7 juin 2017 à 14:42, Vladimir.S  a écrit :
>>
>>
>> Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066
>> but mainly SE-0029 "Remove implicit tuple splat behavior from function
>> applications"
>> (
>> https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md
>> )
>>
>>
>> Do you mean that the regressions Stephen and I have shown have been
>> introduced not only by SE-0110, but before SE-0066, and SE-0029?
>>
>>
>> Your attitude is obnoxious. Enough Swift evolution for me today.
>>
>
> Please refrain from personal attacks. Are we reading the same sentence? I
> see that you literally listed three proposals (and “before”) and blamed
> them for “regressions” that you want to reverse. If that’s not your
> meaning, what do you mean?
>
>
> In the conversation you can see that Vladimir stated that proposing to
> revert this proposal would also mean reverting other previous proposals.
>
> Gwendal is only asking back if the bug was introduced by the changesets
> related to those proposals or by the changesets related to SE-0110.
>
> Asking back is very different from blaming those proposals, or asking for
> reversal of Swift 3 proposals.
>

See, I read that sentence as a rhetorical question, intensifying his claim
of not merely one but all of these proposals being regressions. If that’s
is not what’s intended, that is fine, but he is certainly capable of
replying to my question about his meaning without declaring me to be
‘obnoxious.’

SE-0110 may be an obvious extension of the proposed goal, but it is clear
> that it has been implemented in Swift 4, and that the consequences are
> derived of those changesets.
>
> Those "unwanted" consequences can be reverted by temporarily reverting
> SE-0110, without touching any other previous proposal.
>
> In no place I see Gwendal asking for full reversal of 5 proposals. He is
> just voicing something that a lot of app developers and library maintainers
> are not going to understand in September.
>
> For example, you can see all the changes needed in RXSwift so that it
> compiles to Swift 4:
>
>
> https://github.com/ReactiveX/RxSwift/pull/1282/commits/915e00fa6d1e59d58cd8c38dd6dc83765fc67fe4
>
> I would not want to migrate to Swift 4 an app using such framework.
>
> I asked you in my first reply to you, is your view that the distinction
> itself between (Int, Int) -> Int and ((Int, Int)) -> Int is problematic? If
> so, this is a very different discussion from seeking solutions to mitigate
> particular ergonomic issues that arise from the change. However, you have
> not answered the question.
>
>
> As far as I can see, the bigger usability regressions are caused when
> using generics, specially in collections and functional utilities. When you
> specify that type with a tuple, as in Dictionary, then all the related
> methods start receiving closures receiving tuples.
>
> Notice that allowing some syntactic sugar on the call site of those
> closures may not be enough, since you may have stored or passed a closure
> for customization purposes.
>

Can you illustrate this with an example? I’m not sure I understand what
you’re getting at here.

This behavior is so hurtful to functional style programming, that I think
> either SE-0110 should be reverted, or alternatives like this Susan proposal
> should be implemented.
>

To be clear, what you and Gwendal are objecting to is the loss of tuple
splatting, is it not? Again, SE-0110 is only the final piece; SE-0029 is
what removed implicit tuple splatting. As that proposal said, a properly
designed explicit tuple splatting can be considered if there’s demand, and
it was understood that removing this functionality would be a regression
and nonetheless the decision for removal was still deliberately undertaken.
Re-reading that proposal, the rationale was that it never worked correctly
to begin with, and the barrier for bringing it back is that it requires
considerable effort to design and implement the feature correctly.

However, reverting may be safer and faster than adding more new code to the
> compiler with such short time until Swift 4 release.
>
> Of course that´s the Core team call, if the gains in the compiler code is
> so great then we'll have to live with this regression. After WWDC I hope
> that they notify their decision.
>
> --
> Víctor Pimentel
>

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 20:33, Gwendal Roué  a écrit :
> 
> For example, take those three functions:
> 
>   func f(_ closure:(Int, Int) -> ())
>   func g(_ closure:((Int, Int)) -> ())
>   func h(_ closure:((a: Int, b: Int)) -> ())
> 
> If one can always write (as in Swift 3):
> 
>   f { (a, b) in ... }
>   g { (a, b) in ... }
>   c { (a, b) in ... }
> 
> Then one can easily deal with a badly fit closure signature.
> 
> This is most examplified by dictionaries. They always expose (key: Key, 
> value: Value) tuples (their Element type). Problem is that 'key' and 'value' 
> are identifiers that only matter for dictionaries, not for dictionary users. 
> It's very important for dictionary users to forget about tuples, and the 
> `key` and `value` words:
> 
>   // No pollution
>   dictionary.map { (name, score) in ... }

It looks like some people in this mailing list are horrified by this "request" 
(not a feature request, but a request that Swift 3 behavior is restored, 
actually).

What could be the reasons for such a bad reaction?

1: measurable runtime overhead (slower programs in some cases, without any 
obvious way for the developper to notice where is the extra cost)
2: measurable compiler overhead (slower compilation)
3: implementation complexity (slower swift progress, technical debt, etc.)
4: other?

I understand 1. We are all fascinated by C++ and Rust "zero-overhead". If this 
is the main concern of the community, then we may focus the discussion of that 
very precise topic.

I can live with 2 (just a personal subjective preference)

About 3: I can not tell because I lack the necessary skills.

4: enlighten us!

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 17:15, Vladimir.S  a écrit :
> 
> On 07.06.2017 16:20, Gwendal Roué wrote:
>>> Le 7 juin 2017 à 15:11, Xiaodi Wu >> > a écrit :
>>> 
>>> While SE-0025 was generally regarded as unfortunate, the thousands of 
>>> emails that followed relitigating it were much, much worse.
>>> 
>>> The removal of implicit tuple splatting, which is *not* SE-0110, was 
>>> approved on the understanding that it would be a regression until explicit 
>>> tuple splatting is introduced. This tradeoff was considered and approved. 
>>> It’s clear that you disagree, but that is not grounds to divert a necessary 
>>> discussion on mitigating SE-0110 into relitigating something else.
>> Push me out if you want, but will you push out those blatant wounds out as 
>> well?
>> Example 1
>> -return columns.index { (column, _) in column.lowercased() == 
>> lowercaseName }
>> +return columns.index { $0.0.lowercased() == lowercaseName }
> 
> Why not
> columns.index { (arg: (column: String, _: Int)) in arg.column.lowercased() == 
> lowercaseName }
> ?

It would works, but it's less than ideal: the `args` name has no meaning. We 
have an extra type declaration instead of type inference. It's much longer. The 
clarity is tremendously reduced.

- return columns.index { (column, _) in column.lowercased() == lowercaseName }
+ return columns.index { (arg: (column: String, _)) in arg.column.lowercased() 
== lowercaseName }

> Yes, I understand that first syntax short and not verbose, but the 
> alternative you provided IMHO much worse than explicit type declaration in 
> closure.

It's not an "alternative": it's Swift 3.

Maybe you did already profit from it, but did not notice.

> 
>> Example 2 :
>> -.map { (mappedColumn, baseColumn) -> (Int, String) in
>> +.map { (pair) -> (Int, String) in
>> +let mappedColumn = pair.key
>> +let baseColumn = pair.value
> 
> Can't compile something like this even in Swift 3, could you provide a small 
> code snippet for this?

Sure:

let mapping: [String: String] = ...
mapping.map { (mappedColumn, baseColumn) -> (Int, String) in ... }

>> Example 3 :
>> -.map { (table, columns) in 
>> "\(table)(\(columns.sorted().joined(separator: ", ")))" }
>> +.map { "\($0.key)(\($0.value.sorted().joined(separator: ", 
>> ")))" }
> 
> Same, why not
> 
> .map { (arg: (table: String, columns: [String])) in 
> "\(arg.table)(\(arg.columns.sorted().joined(separator: ", ")))" }

Same answer: the extra `args` works, but we still have an ergonomics regression 
from Swift 3.

>> Example 4 :
>> -dictionary.first { (column, value) in column.lowercased() 
>> == orderedColumn.lowercased() }
>> +dictionary.first { $0.key.lowercased() == 
>> orderedColumn.lowercased() }
> 
> Same.

Indeed.

> 
>> See also messages from Stephen Cellis, who shows how other kinds of 
>> developer code has lost expressivity and clarity with those changes that 
>> have been "considered and approved".
> 
> Gwendal, no one saying that new syntax is better, that it is good thing that 
> we lost the short syntax for tuple argumment deconstructions in closures.

Good to hear :-)

> But there is just no easy/obvious way to keep that syntax in Swift 4. The 
> problem can't be solved just by not implementing SE-0110, as in Swift4 we 
> should have two separate function types: one that takes single tuple argument 
> and second that accepts a list of arguments, i.e. (Int,Int)->() and 
> ((Int,Int))->() should be two different types now.

Of course I understand that.

I expect the compiler to perform the expected conversions for ergonomics' sake.

I can understand that this sugar could be added *after* current problems which 
are not related to ergonomics are solved. I just want to make it clear that 
there is an ergonomics problem *now*, and that solving it should have a very 
high priority.

> This is not just SE-0110, this is also SE-0066, so, to be correct, you should 
> propose to revisit it also.
> 
> Please look here:
> 
> func foo(_ x: Int, _ y: Int) {} // type(of: foo) should be (Int, Int)->()
> func bar(_ x (Int, Int)) {} // type(of: bar) should be ((Int, Int))->()
> 
> The above is described in SE-0066. Then, you have a closure constants:
> 
> var fooClosure = {(x: Int, y: Int) in }
> var barClosure = {(x: (Int, Int)) in }
> 
> what should be types of these closures? Obvious the same: (Int,Int)->() and 
> ((Int,Int))->() respectively.

I guess you mean, not the same: (Int, Int) -> () vs. ((Int, Int)) -> ().

> Then you have a func that accepts ((Int,Int))->Int closure:
> 
> func schedule(callback: ((Int,Int))->()) {..}
> 
> , given type of foo func is (Int, Int)->() , do you suggest to allow sending 
> foo to 'schedule' func? The same question is for fooClosure
> 
> schedule(callback: foo) // ??
> schedule(callback: fooClosure) // ??

Yes, 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Víctor Pimentel Rodríguez via swift-evolution
On 7 Jun 2017, at 18:10, Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

On Wed, Jun 7, 2017 at 10:03 Gwendal Roué  wrote:

> Le 7 juin 2017 à 15:52, Xiaodi Wu  a écrit :
>
> Let’s clarify: you just wrote that you have problems with SE-0029,
> SE-0066, SE-0110, and “before,” did you not?
>
>
> WTF? No I did not (citation below)!
>
> Le 7 juin 2017 à 15:02, Gwendal Roué  a écrit :
>
> Le 7 juin 2017 à 14:42, Vladimir.S  a écrit :
>
>
> Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066
> but mainly SE-0029 "Remove implicit tuple splat behavior from function
> applications"
> (https://github.com/apple/swift-evolution/blob/master/
> proposals/0029-remove-implicit-tuple-splat.md)
>
>
> Do you mean that the regressions Stephen and I have shown have been
> introduced not only by SE-0110, but before SE-0066, and SE-0029?
>
>
> Your attitude is obnoxious. Enough Swift evolution for me today.
>

Please refrain from personal attacks. Are we reading the same sentence? I
see that you literally listed three proposals (and “before”) and blamed
them for “regressions” that you want to reverse. If that’s not your
meaning, what do you mean?


In the conversation you can see that Vladimir stated that proposing to
revert this proposal would also mean reverting other previous proposals.

Gwendal is only asking back if the bug was introduced by the changesets
related to those proposals or by the changesets related to SE-0110.

Asking back is very different from blaming those proposals, or asking for
reversal of Swift 3 proposals. SE-0110 may be an obvious extension of the
proposed goal, but it is clear that it has been implemented in Swift 4, and
that the consequences are derived of those changesets.

Those "unwanted" consequences can be reverted by temporarily reverting
SE-0110, without touching any other previous proposal.

In no place I see Gwendal asking for full reversal of 5 proposals. He is
just voicing something that a lot of app developers and library maintainers
are not going to understand in September.

For example, you can see all the changes needed in RXSwift so that it
compiles to Swift 4:

https://github.com/ReactiveX/RxSwift/pull/1282/commits/915e00fa6d1e59d58cd8c38dd6dc83765fc67fe4

I would not want to migrate to Swift 4 an app using such framework.

I asked you in my first reply to you, is your view that the distinction
itself between (Int, Int) -> Int and ((Int, Int)) -> Int is problematic? If
so, this is a very different discussion from seeking solutions to mitigate
particular ergonomic issues that arise from the change. However, you have
not answered the question.


As far as I can see, the bigger usability regressions are caused when using
generics, specially in collections and functional utilities. When you
specify that type with a tuple, as in Dictionary, then all the related
methods start receiving closures receiving tuples.

Notice that allowing some syntactic sugar on the call site of those
closures may not be enough, since you may have stored or passed a closure
for customization purposes.

This behavior is so hurtful to functional style programming, that I think
either SE-0110 should be reverted, or alternatives like this Susan proposal
should be implemented. However, reverting may be safer and faster than
adding more new code to the compiler with such short time until Swift 4
release.

Of course that´s the Core team call, if the gains in the compiler code is
so great then we'll have to live with this regression. After WWDC I hope
that they notify their decision.

--
Víctor Pimentel
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 10:03 Gwendal Roué  wrote:

> Le 7 juin 2017 à 15:52, Xiaodi Wu  a écrit :
>
> Let’s clarify: you just wrote that you have problems with SE-0029,
> SE-0066, SE-0110, and “before,” did you not?
>
>
> WTF? No I did not (citation below)!
>
> Le 7 juin 2017 à 15:02, Gwendal Roué  a écrit :
>
> Le 7 juin 2017 à 14:42, Vladimir.S  a écrit :
>
>
> Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066
> but mainly SE-0029 "Remove implicit tuple splat behavior from function
> applications"
> (
> https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md
> )
>
>
> Do you mean that the regressions Stephen and I have shown have been
> introduced not only by SE-0110, but before SE-0066, and SE-0029?
>
>
> Your attitude is obnoxious. Enough Swift evolution for me today.
>

Please refrain from personal attacks. Are we reading the same sentence? I
see that you literally listed three proposals (and “before”) and blamed
them for “regressions” that you want to reverse. If that’s not your
meaning, what do you mean?

I asked you in my first reply to you, is your view that the distinction
itself between (Int, Int) -> Int and ((Int, Int)) -> Int is problematic? If
so, this is a very different discussion from seeking solutions to mitigate
particular ergonomic issues that arise from the change. However, you have
not answered the question.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Vladimir.S via swift-evolution

On 07.06.2017 16:20, Gwendal Roué wrote:


Le 7 juin 2017 à 15:11, Xiaodi Wu > a écrit :


While SE-0025 was generally regarded as unfortunate, the thousands of emails that 
followed relitigating it were much, much worse.


The removal of implicit tuple splatting, which is *not* SE-0110, was approved on 
the understanding that it would be a regression until explicit tuple splatting is 
introduced. This tradeoff was considered and approved. It’s clear that you 
disagree, but that is not grounds to divert a necessary discussion on mitigating 
SE-0110 into relitigating something else.


Push me out if you want, but will you push out those blatant wounds out as well?

Example 1
-return columns.index { (column, _) in column.lowercased() == 
lowercaseName }
+return columns.index { $0.0.lowercased() == lowercaseName }


Why not
columns.index { (arg: (column: String, _: Int)) in arg.column.lowercased() == 
lowercaseName }

?

Yes, I understand that first syntax short and not verbose, but the alternative you 
provided IMHO much worse than explicit type declaration in closure.




Example 2 :
-.map { (mappedColumn, baseColumn) -> (Int, String) in
+.map { (pair) -> (Int, String) in
+let mappedColumn = pair.key
+let baseColumn = pair.value



Can't compile something like this even in Swift 3, could you provide a small code 
snippet for this?




Example 3 :
-.map { (table, 
columns) in "\(table)(\(columns.sorted().joined(separator: ", ")))" }

+.map { "\($0.key)(\($0.value.sorted().joined(separator: ", 
")))" }


Same, why not

.map { (arg: (table: String, columns: [String])) in 
"\(arg.table)(\(arg.columns.sorted().joined(separator: ", ")))" }





Example 4 :
-dictionary.first { (column, value) in column.lowercased() == 
orderedColumn.lowercased() }

+dictionary.first { $0.key.lowercased() == 
orderedColumn.lowercased() }



Same.

See also messages from Stephen Cellis, who shows how other kinds of developer code 
has lost expressivity and clarity with those changes that have been "considered and 
approved".




Gwendal, no one saying that new syntax is better, that it is good thing that we lost 
the short syntax for tuple argumment deconstructions in closures.


But there is just no easy/obvious way to keep that syntax in Swift 4. The problem 
can't be solved just by not implementing SE-0110, as in Swift4 we should have two 
separate function types: one that takes single tuple argument and second that accepts 
a list of arguments, i.e. (Int,Int)->() and ((Int,Int))->() should be two different 
types now.


This is not just SE-0110, this is also SE-0066, so, to be correct, you should propose 
to revisit it also.


Please look here:

func foo(_ x: Int, _ y: Int) {} // type(of: foo) should be (Int, Int)->()
func bar(_ x (Int, Int)) {} // type(of: bar) should be ((Int, Int))->()

The above is described in SE-0066. Then, you have a closure constants:

var fooClosure = {(x: Int, y: Int) in }
var barClosure = {(x: (Int, Int)) in }

what should be types of these closures? Obvious the same: (Int,Int)->() and 
((Int,Int))->() respectively.


Then you have a func that accepts ((Int,Int))->Int closure:

func schedule(callback: ((Int,Int))->()) {..}

, given type of foo func is (Int, Int)->() , do you suggest to allow sending foo to 
'schedule' func? The same question is for fooClosure


schedule(callback: foo) // ??
schedule(callback: fooClosure) // ??

Probably we can(if technically possible, I don't know) to always allow sending of 
function/closure with list of arguments when function with one tuple is required. I 
don't know how such exceptional rule would looks like inside type system of Swift, 
what should be result of 'foo is ((Int,Int))->()' then and 'type(of:foo) == 
type(of:bar)' in such case.
But this requires a formal proposal, review period and implementation(as I 
understand, better before Swift 4 release). Probably you can submit such proposal, go 
through the review period and help with implementation.
In this case we'll have the same user-friendly closure/function parameters expirience 
but with respect to correct function types.


But currently we have a situation: argument of type ((Int,Int))->() is required, and 
we provide argument of another type : (Int,Int)->() i.e. incorrect type.
The only obvious solution here is using the common rule for type mismatch - disallow 
this.


Currently we have a number of suggestions how we can improve usability for the 
discussed problem:


* use 'let' syntax in closure argument list to deconstruct tuple argument

* use doubled parenthesis to deconstruct tuple argument: { ((key, value)) in .. 
}

* generation of closure of correct type if closure is declared inside function call 
and arguments have no type annotations, i.e.

  //schedule(callback: foo) // disallowed, type mismatch
  

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 15:52, Xiaodi Wu  a écrit :
> 
> Let’s clarify: you just wrote that you have problems with SE-0029, SE-0066, 
> SE-0110, and “before,” did you not?

WTF? No I did not (citation below)!

> Le 7 juin 2017 à 15:02, Gwendal Roué  a écrit :
> 
>> Le 7 juin 2017 à 14:42, Vladimir.S > > a écrit :
>> 
>> Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066 but 
>> mainly SE-0029 "Remove implicit tuple splat behavior from function 
>> applications"
>> (https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md
>>  
>> )
> 
> Do you mean that the regressions Stephen and I have shown have been 
> introduced not only by SE-0110, but before SE-0066, and SE-0029?

Your attitude is obnoxious. Enough Swift evolution for me today.

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 08:34 Gwendal Roué  wrote:

>
> Le 7 juin 2017 à 15:28, Xiaodi Wu  a écrit :
>
> These *are* changes related to SE-0110, and Chris and others have already
> proposed possibilities for sugar that could make this better. That’s
> exactly the discussion that was originally started, to be distinguished
> from the alternative in which you and others are proposing reversing 5 or 6
> other proposals.
>
>
> That's wrong.
>
> "I and others" have always been after ergonomics regressions, not
> "reversing 5 or 6 other proposals" (how dare you???)
>

Let’s clarify: you just wrote that you have problems with SE-0029, SE-0066,
SE-0110, and “before,” did you not? In addition, Stephen has just said he
disagrees with SE-0155 also, and I’ve outlined how arguments as tuples
impacts SE-0046. That’s five or more proposals by my count–so I should
apologize, it’s only four or more other proposals, not five or six.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 15:28, Xiaodi Wu  a écrit :
> 
> These *are* changes related to SE-0110, and Chris and others have already 
> proposed possibilities for sugar that could make this better. That’s exactly 
> the discussion that was originally started, to be distinguished from the 
> alternative in which you and others are proposing reversing 5 or 6 other 
> proposals.

That's wrong.

"I and others" have always been after ergonomics regressions, not "reversing 5 
or 6 other proposals" (how dare you???)

Gw

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 08:20 Gwendal Roué  wrote:

>
> Le 7 juin 2017 à 15:11, Xiaodi Wu  a écrit :
>
> While SE-0025 was generally regarded as unfortunate, the thousands of
> emails that followed relitigating it were much, much worse.
>
> The removal of implicit tuple splatting, which is *not* SE-0110, was
> approved on the understanding that it would be a regression until explicit
> tuple splatting is introduced. This tradeoff was considered and approved.
> It’s clear that you disagree, but that is not grounds to divert a necessary
> discussion on mitigating SE-0110 into relitigating something else.
>
>
> Push me out if you want, but will you push out those blatant wounds out as
> well?
>
> 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() }
>

These *are* changes related to SE-0110, and Chris and others have already
proposed possibilities for sugar that could make this better. That’s
exactly the discussion that was originally started, to be distinguished
from the alternative in which you and others are proposing reversing 5 or 6
other proposals.

See also messages from Stephen Cellis, who shows how other kinds of
> developer code has lost expressivity and clarity with those changes that
> have been "considered and approved".
>
> Cheers,
> Gwendal
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 15:11, Xiaodi Wu  a écrit :
> 
> While SE-0025 was generally regarded as unfortunate, the thousands of emails 
> that followed relitigating it were much, much worse.
> 
> The removal of implicit tuple splatting, which is *not* SE-0110, was approved 
> on the understanding that it would be a regression until explicit tuple 
> splatting is introduced. This tradeoff was considered and approved. It’s 
> clear that you disagree, but that is not grounds to divert a necessary 
> discussion on mitigating SE-0110 into relitigating something else.

Push me out if you want, but will you push out those blatant wounds out as well?

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() }

See also messages from Stephen Cellis, who shows how other kinds of developer 
code has lost expressivity and clarity with those changes that have been 
"considered and approved".

Cheers,
Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 08:02 Gwendal Roué via swift-evolution <
swift-evolution@swift.org> wrote:

> Le 7 juin 2017 à 14:42, Vladimir.S  a écrit :
>
> On 07.06.2017 14:18, Gwendal Roué via swift-evolution wrote:
>
> Xiaodi, Adrian, you are actively pushing so that something that was
> allowed, well compiled (no runtime issue), and covered actual uses cases,
> becomes forbidden. Without any developer advantage that would somehow
> balance the change.
> That's called a regression.
> And what's the rationale, already? A sense of compiler aesthetics? Since
> when a sense of compiler aesthetics is more valuable than a sense of code
> aesthetics? Aren't both supposed to walk together as a pair?
>
>
> Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066
> but mainly SE-0029 "Remove implicit tuple splat behavior from function
> applications"
> (
> https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md
> )
>
>
> Do you mean that the regressions Stephen and I have shown have been
> introduced not only by SE-0110, but before SE-0066, and SE-0029?
>
> We can discuss what sugar we can have to have tuple destructuring in
> closure and probably some sugar to allow free function of list of arguments
> when function of one tuple is required. But I don't see how we can
> revisit(and I believe we shouldn't) a number of actively discussed(!) and
> accepted proposals and dramatically change direction of Swift evolution
> even because of "lacks in terms of user ergonomics" for some period.
>
>
> I don't know. Nobody seemed to care about regressions, so I felt like it
> was high time some light was shed on them.
>
> Btw, please also note that this will not be possible in Swift 4:
> Probably this "feature" also was used in Swift 3 code, do we need to
> revisit it also? (I believe no)
>
>
> Writing "feature" with ironic quotes is a bad attitude. Some "features"
> are the quality of life of developers.
>
> When proposals are accepted without user feedback, it's reasonable to
> expect that users come back after the harm has been done. It has happened
> before, for fileprivate (SE-0025).
>

While SE-0025 was generally regarded as unfortunate, the thousands of
emails that followed relitigating it were much, much worse.

The removal of implicit tuple splatting, which is *not* SE-0110, was
approved on the understanding that it would be a regression until explicit
tuple splatting is introduced. This tradeoff was considered and approved.
It’s clear that you disagree, but that is not grounds to divert a necessary
discussion on mitigating SE-0110 into relitigating something else.

This is the case now. Some real bad harm to the language ergonomics has
> been done.
>
> Again, I'm not talking about inner compiler design: feel free to do
> whatever is reasonable for Swift and the community. But regressions.
>
> Gwendal
>
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 14:42, Vladimir.S  a écrit :
> 
> On 07.06.2017 14:18, Gwendal Roué via swift-evolution wrote:
>> Xiaodi, Adrian, you are actively pushing so that something that was allowed, 
>> well compiled (no runtime issue), and covered actual uses cases, becomes 
>> forbidden. Without any developer advantage that would somehow balance the 
>> change.
>> That's called a regression.
>> And what's the rationale, already? A sense of compiler aesthetics? Since 
>> when a sense of compiler aesthetics is more valuable than a sense of code 
>> aesthetics? Aren't both supposed to walk together as a pair?
> 
> Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066 but 
> mainly SE-0029 "Remove implicit tuple splat behavior from function 
> applications"
> (https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md
>  
> )

Do you mean that the regressions Stephen and I have shown have been introduced 
not only by SE-0110, but before SE-0066, and SE-0029?

> We can discuss what sugar we can have to have tuple destructuring in closure 
> and probably some sugar to allow free function of list of arguments when 
> function of one tuple is required. But I don't see how we can revisit(and I 
> believe we shouldn't) a number of actively discussed(!) and accepted 
> proposals and dramatically change direction of Swift evolution even because 
> of "lacks in terms of user ergonomics" for some period.

I don't know. Nobody seemed to care about regressions, so I felt like it was 
high time some light was shed on them.

> Btw, please also note that this will not be possible in Swift 4:
> Probably this "feature" also was used in Swift 3 code, do we need to revisit 
> it also? (I believe no)

Writing "feature" with ironic quotes is a bad attitude. Some "features" are the 
quality of life of developers.

When proposals are accepted without user feedback, it's reasonable to expect 
that users come back after the harm has been done. It has happened before, for 
fileprivate (SE-0025). This is the case now. Some real bad harm to the language 
ergonomics has been done.

Again, I'm not talking about inner compiler design: feel free to do whatever is 
reasonable for Swift and the community. But regressions.

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 07:40 Stephen Celis  wrote:

> > On Jun 7, 2017, at 8:27 AM, Xiaodi Wu  wrote:
> >
> > Swift package descriptions make extensive use of enums. For example,
> .target(...) is an enum case with an associated value, unless I’m mistaken.
> I too got the order of “dependencies” and “path” reversed the other day; if
> enum associated values were tuples, then it would not have mattered. I
> assume this is what you were referring to above.
>
> Enum associated values are isomorphic to tuples. Function arguments are
> also isomorphic to tuples. You're referring to a specific ordering issue
> that exists in both enum cases with multiple associated values, functions
> arguments (like a struct initializer), and tuples.


I’m not sure what you’re getting at. My point is that tuples currently
allow “shuffling” with labels but argument lists do not, and that enum
associated values were recently revised to be initialized with an argument
list and not a tuple, although that proposal is not fully implemented.

> An arbitrary argument list cannot be represented as a tuple. For example,
> tuples cannot have elements of variadic type or inout type.
>
> Modifiers like throws/inout/@escaping affect the body of the function and
> are arguably erasable in the data structure itself.


An early proposal moved the placement of inout to reflect the fact that
`inout T` is a distinct type from `T`. Escaping vs. non-escaping closures
also have type system significance, afaik; this is why
`withoutActuallyEscaping` required quite a bit of cleverness to implement
and cannot be expressed in Swift itself. In any case, the compiler itself
no longer represents argument lists as tuples, and that distinction is
fully plumbed through, unless I’m mistaken.

Variadic tuples are disallowed but not an impossible concept (and
> supporting them hasn't been ruled out as far as I can remember).
>
> > Slow, and especially inconsistently slow, performance fits the
> definition of unreliable, wouldn’t you agree?
>
> Again, trade-offs and openness to exploring better solutions.
>
> > They are not.
>
> Other than the function body modifiers, how are they not?


Literally, they are not the same, neither in syntax, nor in the way they
are modeled by the compiler.

Stephen
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Stephen Celis via swift-evolution
> On Jun 7, 2017, at 8:27 AM, Xiaodi Wu  wrote:
> 
> Swift package descriptions make extensive use of enums. For example, 
> .target(...) is an enum case with an associated value, unless I’m mistaken. I 
> too got the order of “dependencies” and “path” reversed the other day; if 
> enum associated values were tuples, then it would not have mattered. I assume 
> this is what you were referring to above.

Enum associated values are isomorphic to tuples. Function arguments are also 
isomorphic to tuples. You're referring to a specific ordering issue that exists 
in both enum cases with multiple associated values, functions arguments (like a 
struct initializer), and tuples.

> An arbitrary argument list cannot be represented as a tuple. For example, 
> tuples cannot have elements of variadic type or inout type.

Modifiers like throws/inout/@escaping affect the body of the function and are 
arguably erasable in the data structure itself.

Variadic tuples are disallowed but not an impossible concept (and supporting 
them hasn't been ruled out as far as I can remember).

> Slow, and especially inconsistently slow, performance fits the definition of 
> unreliable, wouldn’t you agree?

Again, trade-offs and openness to exploring better solutions.

> They are not.

Other than the function body modifiers, how are they not?

Stephen

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution
I disagree it almost feels like a revert of SE–0110. If we had more than only:

parentheses
(angle) brackets
braces
A fifth set, that would also look visually fine with tuples. This discussion 
would not even exist, no matter if the data structure behind the scenes is the 
same or not. Parameter list should stay as a list of types for a closure, 
nothing more nothing less (it can be baked as a tuple behind the scenes, but 
that’s not the main discussion here).

( ❲ Int, Int ❳ ) -> Void

is different from

( Int, Int ) -> Void



-- 
Adrian Zubarev
Sent with Airmail

Am 7. Juni 2017 um 14:17:05, Stephen Celis via swift-evolution 
(swift-evolution@swift.org) schrieb:

Susan's proposal is an elegant step towards fixing some of the issues we've 
been having while specifically preventing previous ambiguities
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 07:16 Stephen Celis  wrote:

> > On Jun 7, 2017, at 2:01 AM, Xiaodi Wu  wrote:
> >
> > Those are enums, which were aligned with argument lists instead of
> tuples in yet another proposal, SE-0155.
>
> Can you clarify? I wasn't referring to enums, and SE-0155 starts by
> talking about single enum cases with multiple associated values being
> represented by a tuple.


Swift package descriptions make extensive use of enums. For example,
.target(...) is an enum case with an associated value, unless I’m mistaken.
I too got the order of “dependencies” and “path” reversed the other day; if
enum associated values were tuples, then it would not have mattered. I
assume this is what you were referring to above.

The root values of tuples and structs are product types while enums are sum
> types. In general, anything with multiple configurable values at the same
> time are representable by tuples, and argument lists are no exception.


An arbitrary argument list cannot be represented as a tuple. For example,
tuples cannot have elements of variadic type or inout type.

> Having the compiler perform reliably is the most basic of user
> ergonomics, wouldn’t you say?
>
> Can you clarify what you mean by "reliably"? My understanding was the
> compiler performed reliably, but more slowly, with more tech debt.


Slow, and especially inconsistently slow, performance fits the definition
of unreliable, wouldn’t you agree?

Regardless, why not explore paths that improve both and aren't trade-offs?
>
> The separation of argument lists and tuples was approached in a very
> specific way to eliminate a very specific ambiguity, but the data
> structures are the same.


They are not.

Susan's proposal is an elegant step towards fixing some of the issues we've
> been having while specifically preventing previous ambiguities.
>
> Stephen
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Stephen Celis via swift-evolution
> On Jun 7, 2017, at 2:01 AM, Xiaodi Wu  wrote:
> 
> Those are enums, which were aligned with argument lists instead of tuples in 
> yet another proposal, SE-0155.

Can you clarify? I wasn't referring to enums, and SE-0155 starts by talking 
about single enum cases with multiple associated values being represented by a 
tuple.

The root values of tuples and structs are product types while enums are sum 
types. In general, anything with multiple configurable values at the same time 
are representable by tuples, and argument lists are no exception.

> Having the compiler perform reliably is the most basic of user ergonomics, 
> wouldn’t you say?

Can you clarify what you mean by "reliably"? My understanding was the compiler 
performed reliably, but more slowly, with more tech debt. Regardless, why not 
explore paths that improve both and aren't trade-offs?

The separation of argument lists and tuples was approached in a very specific 
way to eliminate a very specific ambiguity, but the data structures are the 
same. Susan's proposal is an elegant step towards fixing some of the issues 
we've been having while specifically preventing previous ambiguities.

Stephen

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution
( /* two parameters, not a tuple */ (Int, Int) -> Void).self == (( /* one tuple 
parameter */ (Int, Int)) -> Void).self // BUG, which SE-0110 should have fixed, 
but still didn't

Plus inlined:

-- 
Adrian Zubarev
Sent with Airmail

Am 7. Juni 2017 um 13:53:08, Gwendal Roué (gwendal.r...@gmail.com) schrieb:

    func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
    func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
    func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
    func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs + 
tuple.rhs }

    // two arguments
    func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
Bug abuse:

    f1 { tuple in tuple.0 + tuple.1 }
    f1 { (tuple) in tuple.0 + tuple.1 }
    f1(sum3)
    f1(sum4)

`f2` is no different from `f1`.

Bugs, which should be fixed by `((lhs, rhs)) in`:

    // one tuple argument
    func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
    f3 { lhs, rhs in lhs + rhs }
    f3 { (lhs, rhs) in lhs + rhs }
Not possible because ultimately the closures have different types.

    f3(+)
    f3(sum1)
    f3(sum2)    
Bugs, which should be fixed by `((lhs, rhs)) in`:

    // one keyed tuple argument
    func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
    f4 { lhs, rhs in lhs + rhs }
    f4 { (lhs, rhs) in lhs + rhs }
Not possible because ultimately the closures have different types.

    f4(+)
    f4(sum1)
    f4(sum2)
Not sure, but I assume this shouldn’t be possible because tuple labels are part 
of the type and it’s a mismatch like `(lhs: Int, rhs: Int).Type != (a: Int, b: 
Int).Type`, therefore closures should be of different types as well.

    f4(sum4)





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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 13:28, Adrian Zubarev  a 
> écrit :
> 
>> Xiaodi, Adrian, you are actively pushing so that something that was allowed, 
>> well compiled (no runtime issue), and covered actual uses cases, becomes 
>> forbidden. Without any developer advantage that would somehow balance the 
>> change.
>> 
>> That's called a regression.
> 
> 
> func foo(_: (Int, Int)) {}
> func bar(_: Int, _: Int) {}
> 
> type(of: foo) == type(of: bar) //=> true - It's a BUG!

Then please push for the bug to be fixed. You are much better than am I at 
that. This does not mean breaking Swift 3 ergonomics.

The bug you mention involves type comparison, which is nowhere to be seen in 
the Swift 3 ergonomics checklist below. I'm sure we can all be happy.

func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs + 
tuple.rhs }

// two arguments
func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
f1 { lhs, rhs in lhs + rhs }
f1 { (lhs, rhs) in lhs + rhs }
f1 { tuple in tuple.0 + tuple.1 }
f1 { (tuple) in tuple.0 + tuple.1 }
f1(+)
f1(sum1)
f1(sum2)
f1(sum3)
f1(sum4)

// two arguments, with documentation names
func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
f2 { lhs, rhs in lhs + rhs }
f2 { (lhs, rhs) in lhs + rhs }
f2 { tuple in tuple.0 + tuple.1 }
f2 { (tuple) in tuple.0 + tuple.1 }
f2(+)
f2(sum1)
f2(sum2)
f2(sum3)
f2(sum4)

// one tuple argument
func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
f3 { lhs, rhs in lhs + rhs }
f3 { (lhs, rhs) in lhs + rhs }
f3 { tuple in tuple.0 + tuple.1 }
f3 { (tuple) in tuple.0 + tuple.1 }
f3(+)
f3(sum1)
f3(sum2)
f3(sum3)
f3(sum4)

// one keyed tuple argument
func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
f4 { lhs, rhs in lhs + rhs }
f4 { (lhs, rhs) in lhs + rhs }
f4 { tuple in tuple.a + tuple.b }
f4 { (tuple) in tuple.a + tuple.b }
f4(+)
f4(sum1)
f4(sum2)
f4(sum3)
f4(sum4)

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 06:18 Gwendal Roué  wrote:

> Xiaodi, Adrian, you are actively pushing so that something that was
> allowed, well compiled (no runtime issue), and covered actual uses cases,
> becomes forbidden.
>

To be clear, I’m not pushing to forbid anything at all. SE-0110 prohibited
this a long time ago.

Without any developer advantage that would somehow balance the change.
>
> That's called a regression.
>
> And what's the rationale, already?
>

Surely, the time to ask that question was during review of SE-0110. Today’s
question is: how do we improve the user experience given that tuples and
argument lists are now distinct? Is your starting point that you reject
that conclusion altogether? If so, we’re simply having distinct discussions.

A sense of compiler aesthetics? Since when a sense of compiler aesthetics
> is more valuable than a sense of code aesthetics? Aren't both supposed to
> walk together as a pair?
>
> Gwendal
>
> Le 7 juin 2017 à 12:54, Xiaodi Wu  a écrit :
>
> IMO, if tuples and argument lists are to be distinguished in any way, it
> is imperative that f3(+) and f4(+), and some of your other examples, _not_
> work.
>
> After all, if a tuple is not an argument list, it should possible to have
> a function of type ((Int, Int)) -> Int and a function of type (Int, Int) ->
> Int share the same name (IIUC, it’s a known bug that this does not
> currently work). Quite simply, there’s a type mismatch if you pass sum1 to
> f3–what happens if there’s a distinct, overloaded sum1 that takes a single
> tuple?
>
> Chris’s suggestion restores a syntactic convenience without touching the
> type system. What you are arguing for is essentially making ((Int, Int)) ->
> Int and (Int, Int) -> Int synonymous again, either in some or in all
> contexts.
>
>
> On Wed, Jun 7, 2017 at 05:41 Gwendal Roué via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Le 7 juin 2017 à 12:33, Gwendal Roué  a écrit :
>>
>>
>> Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution <
>> swift-evolution@swift.org> a écrit :
>>
>> Well please no:
>>
>>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in }
>>
>> Instead use destructuring sugar pitched by Chris Lattner on the other
>> thread:
>>
>> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>>
>>
>> Despite Chris Lattern being a semi-god, his double-parenthesis suggestion
>> cruelly lacks in terms of user ergonomics. The compiler should be able to
>> deal with the following code snippet, just like Swift 3 does:
>>
>> // two arguments
>> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
>>
>> [...]
>>
>>
>> Here is the full extent of the remarquable Swift 3 ergonomics. This full
>> snippet compiles in Swift 3:
>>
>> func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
>> func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
>> func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
>> func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs +
>> tuple.rhs }
>>
>> // two arguments
>> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
>> f1 { lhs, rhs in lhs + rhs }
>> f1 { (lhs, rhs) in lhs + rhs }
>> f1 { tuple in tuple.0 + tuple.1 }
>> f1 { (tuple) in tuple.0 + tuple.1 }
>> f1(+)
>> f1(sum1)
>> f1(sum2)
>> f1(sum3)
>> f1(sum4)
>>
>> // two arguments, with documentation names: identical
>> func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
>> f2 { lhs, rhs in lhs + rhs }
>> f2 { (lhs, rhs) in lhs + rhs }
>> f2 { tuple in tuple.0 + tuple.1 }
>> f2 { (tuple) in tuple.0 + tuple.1 }
>> f2(+)
>> f2(sum1)
>> f2(sum2)
>> f2(sum3)
>> f2(sum4)
>>
>> // one tuple argument
>> func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
>> f3 { lhs, rhs in lhs + rhs }
>> f3 { (lhs, rhs) in lhs + rhs }
>> f3 { tuple in tuple.0 + tuple.1 }
>> f3 { (tuple) in tuple.0 + tuple.1 }
>> f3(+)
>> f3(sum1)
>> f3(sum2)
>> f3(sum3)
>> f3(sum4)
>>
>> // one keyed tuple argument
>> func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b:
>> 2)) }
>> f4 { lhs, rhs in lhs + rhs }
>> f4 { (lhs, rhs) in lhs + rhs }
>> f4 { tuple in tuple.a + tuple.b }
>> f4 { (tuple) in tuple.a + tuple.b }
>> f4(+)
>> f4(sum1)
>> f4(sum2)
>> f4(sum3)
>> f4(sum4)
>>
>> Gwendal
>>
>> ___
>> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution


-- 
Adrian Zubarev
Sent with Airmail

Am 7. Juni 2017 um 13:18:22, Gwendal Roué (gwendal.r...@gmail.com) schrieb:

Xiaodi, Adrian, you are actively pushing so that something that was allowed, 
well compiled (no runtime issue), and covered actual uses cases, becomes 
forbidden. Without any developer advantage that would somehow balance the 
change.

That's called a regression.

func foo(_: (Int, Int)) {}
func bar(_: Int, _: Int) {}
type(of: foo) == type(of: bar) //=> true - It's a BUG!


And what's the rationale, already? A sense of compiler aesthetics? Since when a 
sense of compiler aesthetics is more valuable than a sense of code aesthetics? 
Aren't both supposed to walk together as a pair?

Gwendal

Le 7 juin 2017 à 12:54, Xiaodi Wu  a écrit :

IMO, if tuples and argument lists are to be distinguished in any way, it is 
imperative that f3(+) and f4(+), and some of your other examples, _not_ work.

After all, if a tuple is not an argument list, it should possible to have a 
function of type ((Int, Int)) -> Int and a function of type (Int, Int) -> Int 
share the same name (IIUC, it’s a known bug that this does not currently work). 
Quite simply, there’s a type mismatch if you pass sum1 to f3–what happens if 
there’s a distinct, overloaded sum1 that takes a single tuple?

Chris’s suggestion restores a syntactic convenience without touching the type 
system. What you are arguing for is essentially making ((Int, Int)) -> Int and 
(Int, Int) -> Int synonymous again, either in some or in all contexts.


On Wed, Jun 7, 2017 at 05:41 Gwendal Roué via swift-evolution 
 wrote:
Le 7 juin 2017 à 12:33, Gwendal Roué  a écrit :


Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution 
 a écrit :

Well please no:


 let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }


Despite Chris Lattern being a semi-god, his double-parenthesis suggestion 
cruelly lacks in terms of user ergonomics. The compiler should be able to deal 
with the following code snippet, just like Swift 3 does:

    // two arguments
    func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
[...]

Here is the full extent of the remarquable Swift 3 ergonomics. This full 
snippet compiles in Swift 3:

    func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
    func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
    func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
    func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs + 
tuple.rhs }

    // two arguments
    func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
    f1 { lhs, rhs in lhs + rhs }
    f1 { (lhs, rhs) in lhs + rhs }
    f1 { tuple in tuple.0 + tuple.1 }
    f1 { (tuple) in tuple.0 + tuple.1 }
    f1(+)
    f1(sum1)
    f1(sum2)
    f1(sum3)
    f1(sum4)
    
    // two arguments, with documentation names: identical
    func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
    f2 { lhs, rhs in lhs + rhs }
    f2 { (lhs, rhs) in lhs + rhs }
    f2 { tuple in tuple.0 + tuple.1 }
    f2 { (tuple) in tuple.0 + tuple.1 }
    f2(+)
    f2(sum1)
    f2(sum2)
    f2(sum3)
    f2(sum4)
    
    // one tuple argument
    func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
    f3 { lhs, rhs in lhs + rhs }
    f3 { (lhs, rhs) in lhs + rhs }
    f3 { tuple in tuple.0 + tuple.1 }
    f3 { (tuple) in tuple.0 + tuple.1 }
    f3(+)
    f3(sum1)
    f3(sum2)
    f3(sum3)
    f3(sum4)
    
    // one keyed tuple argument
    func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
    f4 { lhs, rhs in lhs + rhs }
    f4 { (lhs, rhs) in lhs + rhs }
    f4 { tuple in tuple.a + tuple.b }
    f4 { (tuple) in tuple.a + tuple.b }
    f4(+)
    f4(sum1)
    f4(sum2)
    f4(sum3)
    f4(sum4)

Gwendal

___
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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution
Xiaodi, Adrian, you are actively pushing so that something that was allowed, 
well compiled (no runtime issue), and covered actual uses cases, becomes 
forbidden. Without any developer advantage that would somehow balance the 
change.

That's called a regression.

And what's the rationale, already? A sense of compiler aesthetics? Since when a 
sense of compiler aesthetics is more valuable than a sense of code aesthetics? 
Aren't both supposed to walk together as a pair?

Gwendal

> Le 7 juin 2017 à 12:54, Xiaodi Wu  a écrit :
> 
> IMO, if tuples and argument lists are to be distinguished in any way, it is 
> imperative that f3(+) and f4(+), and some of your other examples, _not_ work.
> 
> After all, if a tuple is not an argument list, it should possible to have a 
> function of type ((Int, Int)) -> Int and a function of type (Int, Int) -> Int 
> share the same name (IIUC, it’s a known bug that this does not currently 
> work). Quite simply, there’s a type mismatch if you pass sum1 to f3–what 
> happens if there’s a distinct, overloaded sum1 that takes a single tuple?
> 
> Chris’s suggestion restores a syntactic convenience without touching the type 
> system. What you are arguing for is essentially making ((Int, Int)) -> Int 
> and (Int, Int) -> Int synonymous again, either in some or in all contexts.
> 
> 
> On Wed, Jun 7, 2017 at 05:41 Gwendal Roué via swift-evolution 
> > wrote:
>> Le 7 juin 2017 à 12:33, Gwendal Roué > > a écrit :
>> 
>> 
>>> Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution 
>>> > a écrit :
>>> 
>>> Well please no:
>>> 
>>> 
>>>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
>>> 
>>> Instead use destructuring sugar pitched by Chris Lattner on the other 
>>> thread:
>>> 
>>> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>>> 
>> 
>> Despite Chris Lattern being a semi-god, his double-parenthesis suggestion 
>> cruelly lacks in terms of user ergonomics. The compiler should be able to 
>> deal with the following code snippet, just like Swift 3 does:
>> 
>> // two arguments
>> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
> 
>> [...]
> 
> Here is the full extent of the remarquable Swift 3 ergonomics. This full 
> snippet compiles in Swift 3:
> 
> func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
> func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
> func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
> func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs + 
> tuple.rhs }
> 
> // two arguments
> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
> f1 { lhs, rhs in lhs + rhs }
> f1 { (lhs, rhs) in lhs + rhs }
> f1 { tuple in tuple.0 + tuple.1 }
> f1 { (tuple) in tuple.0 + tuple.1 }
> f1(+)
> f1(sum1)
> f1(sum2)
> f1(sum3)
> f1(sum4)
> 
> // two arguments, with documentation names: identical
> func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
> f2 { lhs, rhs in lhs + rhs }
> f2 { (lhs, rhs) in lhs + rhs }
> f2 { tuple in tuple.0 + tuple.1 }
> f2 { (tuple) in tuple.0 + tuple.1 }
> f2(+)
> f2(sum1)
> f2(sum2)
> f2(sum3)
> f2(sum4)
> 
> // one tuple argument
> func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
> f3 { lhs, rhs in lhs + rhs }
> f3 { (lhs, rhs) in lhs + rhs }
> f3 { tuple in tuple.0 + tuple.1 }
> f3 { (tuple) in tuple.0 + tuple.1 }
> f3(+)
> f3(sum1)
> f3(sum2)
> f3(sum3)
> f3(sum4)
> 
> // one keyed tuple argument
> func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
> f4 { lhs, rhs in lhs + rhs }
> f4 { (lhs, rhs) in lhs + rhs }
> f4 { tuple in tuple.a + tuple.b }
> f4 { (tuple) in tuple.a + tuple.b }
> f4(+)
> f4(sum1)
> f4(sum2)
> f4(sum3)
> f4(sum4)
> 
> Gwendal
> 
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
IMO, if tuples and argument lists are to be distinguished in any way, it is
imperative that f3(+) and f4(+), and some of your other examples, _not_
work.

After all, if a tuple is not an argument list, it should possible to have a
function of type ((Int, Int)) -> Int and a function of type (Int, Int) ->
Int share the same name (IIUC, it’s a known bug that this does not
currently work). Quite simply, there’s a type mismatch if you pass sum1 to
f3–what happens if there’s a distinct, overloaded sum1 that takes a single
tuple?

Chris’s suggestion restores a syntactic convenience without touching the
type system. What you are arguing for is essentially making ((Int, Int)) ->
Int and (Int, Int) -> Int synonymous again, either in some or in all
contexts.


On Wed, Jun 7, 2017 at 05:41 Gwendal Roué via swift-evolution <
swift-evolution@swift.org> wrote:

> Le 7 juin 2017 à 12:33, Gwendal Roué  a écrit :
>
>
> Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution <
> swift-evolution@swift.org> a écrit :
>
> Well please no:
>
>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in }
>
> Instead use destructuring sugar pitched by Chris Lattner on the other
> thread:
>
> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>
>
> Despite Chris Lattern being a semi-god, his double-parenthesis suggestion
> cruelly lacks in terms of user ergonomics. The compiler should be able to
> deal with the following code snippet, just like Swift 3 does:
>
> // two arguments
> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
>
> [...]
>
>
> Here is the full extent of the remarquable Swift 3 ergonomics. This full
> snippet compiles in Swift 3:
>
> func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
> func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
> func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
> func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs +
> tuple.rhs }
>
> // two arguments
> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
> f1 { lhs, rhs in lhs + rhs }
> f1 { (lhs, rhs) in lhs + rhs }
> f1 { tuple in tuple.0 + tuple.1 }
> f1 { (tuple) in tuple.0 + tuple.1 }
> f1(+)
> f1(sum1)
> f1(sum2)
> f1(sum3)
> f1(sum4)
>
>
> // two arguments, with documentation names: identical
> func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
> f2 { lhs, rhs in lhs + rhs }
> f2 { (lhs, rhs) in lhs + rhs }
> f2 { tuple in tuple.0 + tuple.1 }
> f2 { (tuple) in tuple.0 + tuple.1 }
> f2(+)
> f2(sum1)
> f2(sum2)
> f2(sum3)
> f2(sum4)
>
>
> // one tuple argument
> func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
> f3 { lhs, rhs in lhs + rhs }
> f3 { (lhs, rhs) in lhs + rhs }
> f3 { tuple in tuple.0 + tuple.1 }
> f3 { (tuple) in tuple.0 + tuple.1 }
> f3(+)
> f3(sum1)
> f3(sum2)
> f3(sum3)
> f3(sum4)
>
>
> // one keyed tuple argument
> func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2))
> }
> f4 { lhs, rhs in lhs + rhs }
> f4 { (lhs, rhs) in lhs + rhs }
> f4 { tuple in tuple.a + tuple.b }
> f4 { (tuple) in tuple.a + tuple.b }
> f4(+)
> f4(sum1)
> f4(sum2)
> f4(sum3)
> f4(sum4)
>
> Gwendal
>
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution

Answer inlined:
Am 7. Juni 2017 um 12:33:51, Gwendal Roué (gwendal.r...@gmail.com) schrieb:


Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution 
 a écrit :

Well please no:


 let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }


Despite Chris Lattern being a semi-god, his double-parenthesis suggestion 
cruelly lacks in terms of user ergonomics. 
Well it’s clearly not the ideal solution from a visual perspective but it’s an 
unambiguous one. If tuples were represented differently, let’s say `@(a, b)` we 
wouldn’t sit here and debate that long because it becomes crystal clear what 
should be possible and what not.



The compiler should be able to deal with the following code snippet, just like 
Swift 3 does:

    // two arguments
    func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
    f1 { lhs, rhs in lhs + rhs }
    f1 { (lhs, rhs) in lhs + rhs }
Next one is a bug to me:


    f1 { tuple in tuple.0 + tuple.1 }
Fine:


    f1(+)
    
    // two arguments, with documentation names
    func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
    f2 { lhs, rhs in lhs + rhs }
    f2 { (lhs, rhs) in lhs + rhs }
Another bug to me:


    f2 { tuple in tuple.0 + tuple.1 }
Fine:


    f2(+)
    
    // one tuple argument
    func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
Should be `((lhs, rhs)) in` which eliminates both of the next two scenarios 
completely:


    f3 { lhs, rhs in lhs + rhs }
    f3 { (lhs, rhs) in lhs + rhs }
Fine:


    f3 { tuple in tuple.0 + tuple.1 }
Should be an error:


    f3(+)
See `f3`


    
    // one keyed tuple argument
    func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
    f4 { lhs, rhs in lhs + rhs }
    f4 { (lhs, rhs) in lhs + rhs }
    f4 { tuple in tuple.a + tuple.b }
    f4(+)

This covers the Swift 3 regressions developped by Stephen Celis and I, unless I 
have missed any. And this should be the goal of the designers of this language, 
*regardless of the actual types*. Developers are olding their breath: please 
just make this happen.

Now Swift 3 may have an issue with $n parameters. Here is my suggestion, should 
`((Int, Int)) -> Int` be different from `(Int, Int) -> Int`:


That’s what I would expect.

    f1 { $0 + $1 } // OK
    f1 { $0.0 + $0.1 } // OK in Swift 3, compiler error in Swift 4?
    
    f2 { $0 + $1 } // OK
    f2 { $0.0 + $0.1 } // OK in Swift 3, compiler error in Swift 4?
    
    f3 { $0 + $1 } // OK in Swift 3, compiler error in Swift 4?
    f3 { $0.0 + $0.1 } // OK
    
    f4 { $0 + $1 } // OK in Swift 3, compiler error in Swift 4?
    f4 { $0.a + $0.b } // OK

Gwendal Roué


These rules should as strict as they possible can be now. Later on we can add 
sugar to relax some of them. Here is a quote, again from Chris Lattner:

The art of evolving Swift forward is to carefully pick and choose areas to 
focus on, both because we want to ensure a coherent language, but also because 
implementor bandwidth is limited.

Beyond that, though syntactic sugar is always motivated by strong rationale and 
use-cases, in my opinion, it is the most dangerous kind of additive feature to 
consider at this point of Swift’s evolution. While these features are useful, 
they also clearly add complexity to the language, and it is difficult to gauge 
whether the problem being addressed will even exist in Swift as the other 
bigger features come in (for example, a macro system). These features can also 
make future language evolution more problematic because they consume syntactic 
real estate in the language.

If you’re into analogies, I see features like the generics improvements, 
ownership model, concurrency model, macro system, new frameworks, and other 
large scale efforts as the “bricks" that make up the house of Swift. In that 
analogy, syntactic sugar proposals are “mortar” that fills in the cracks 
between the bricks. If we add too much mortar too early on, we run the risk of 
the house of Swift being built out of mortar, or of not being able to fit the 
bricks into the right places. That would be very bad, given that we all want 
the house of Swift to be strong and beautiful over the long term.

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 12:33, Gwendal Roué  a écrit :
> 
> 
>> Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution 
>> > a écrit :
>> 
>> Well please no:
>> 
>> 
>>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
>> 
>> Instead use destructuring sugar pitched by Chris Lattner on the other thread:
>> 
>> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>> 
> 
> Despite Chris Lattern being a semi-god, his double-parenthesis suggestion 
> cruelly lacks in terms of user ergonomics. The compiler should be able to 
> deal with the following code snippet, just like Swift 3 does:
> 
> // two arguments
> func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
> [...]

Here is the full extent of the remarquable Swift 3 ergonomics. This full 
snippet compiles in Swift 3:

func sum1(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }
func sum2(lhs: Int, rhs: Int) -> Int { return lhs + rhs }
func sum3(tuple: (Int, Int)) -> Int { return tuple.0 + tuple.1 }
func sum4(tuple: (lhs: Int, rhs: Int)) -> Int { return tuple.lhs + 
tuple.rhs }

// two arguments
func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
f1 { lhs, rhs in lhs + rhs }
f1 { (lhs, rhs) in lhs + rhs }
f1 { tuple in tuple.0 + tuple.1 }
f1 { (tuple) in tuple.0 + tuple.1 }
f1(+)
f1(sum1)
f1(sum2)
f1(sum3)
f1(sum4)

// two arguments, with documentation names: identical
func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
f2 { lhs, rhs in lhs + rhs }
f2 { (lhs, rhs) in lhs + rhs }
f2 { tuple in tuple.0 + tuple.1 }
f2 { (tuple) in tuple.0 + tuple.1 }
f2(+)
f2(sum1)
f2(sum2)
f2(sum3)
f2(sum4)

// one tuple argument
func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
f3 { lhs, rhs in lhs + rhs }
f3 { (lhs, rhs) in lhs + rhs }
f3 { tuple in tuple.0 + tuple.1 }
f3 { (tuple) in tuple.0 + tuple.1 }
f3(+)
f3(sum1)
f3(sum2)
f3(sum3)
f3(sum4)

// one keyed tuple argument
func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
f4 { lhs, rhs in lhs + rhs }
f4 { (lhs, rhs) in lhs + rhs }
f4 { tuple in tuple.a + tuple.b }
f4 { (tuple) in tuple.a + tuple.b }
f4(+)
f4(sum1)
f4(sum2)
f4(sum3)
f4(sum4)

Gwendal

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution
Well I’m clearly against this, it doesn’t hurt to use some more paeans inside a 
closure to tell the compiler if you want to destructure a tuple or use a single 
argument for the whole tuple.



-- 
Adrian Zubarev
Sent with Airmail

Am 7. Juni 2017 um 12:31:47, Susan Cheng (susan.dog...@gmail.com) schrieb:

`((Int, Int)) -> Void` will be same type as `(Int, Int) -> Void`

2017-06-07 18:09 GMT+08:00 Adrian Zubarev :
Keep in mind there is also SE–0111 cometary which promises sugar for parameter 
labels for closures:

// **
let foo(tuple:): ((Int, Int)) -> Void

// Sugar for **
let foo: (tuple: (Int, Int)) -> Void
What will happen if you’d always flatten here?



-- 
Adrian Zubarev
Sent with Airmail

Am 7. Juni 2017 um 12:03:08, Adrian Zubarev (adrian.zuba...@devandartist.com) 
schrieb:

Well please no:


let fn2: ((Int, Int)) -> Void = { lhs, rhs in }

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }

That’s a correct error:

let fn3: (Int, Int) -> Void = { _ in }
This should be allowed, because we might want to work with the whole tuple and 
not a desctructured elements only:

let fn4: ((Int, Int)) -> Void = { tuple in }


-- 
Adrian Zubarev
Sent with Airmail

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Gwendal Roué via swift-evolution

> Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution 
>  a écrit :
> 
> Well please no:
> 
> 
>  let fn2: ((Int, Int)) -> Void = { lhs, rhs in } 
> 
> Instead use destructuring sugar pitched by Chris Lattner on the other thread:
> 
> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
> 

Despite Chris Lattern being a semi-god, his double-parenthesis suggestion 
cruelly lacks in terms of user ergonomics. The compiler should be able to deal 
with the following code snippet, just like Swift 3 does:

// two arguments
func f1(_ closure: (Int, Int) -> Int) { closure(1, 2) }
f1 { lhs, rhs in lhs + rhs }
f1 { (lhs, rhs) in lhs + rhs }
f1 { tuple in tuple.0 + tuple.1 }
f1(+)

// two arguments, with documentation names
func f2(_ closure: (_ a: Int, _ b: Int) -> Int) { closure(1, 2) }
f2 { lhs, rhs in lhs + rhs }
f2 { (lhs, rhs) in lhs + rhs }
f2 { tuple in tuple.0 + tuple.1 }
f2(+)

// one tuple argument
func f3(_ closure: ((Int, Int)) -> Int) { closure((1, 2)) }
f3 { lhs, rhs in lhs + rhs }
f3 { (lhs, rhs) in lhs + rhs }
f3 { tuple in tuple.0 + tuple.1 }
f3(+)

// one keyed tuple argument
func f4(_ closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
f4 { lhs, rhs in lhs + rhs }
f4 { (lhs, rhs) in lhs + rhs }
f4 { tuple in tuple.a + tuple.b }
f4(+)

This covers the Swift 3 regressions developped by Stephen Celis and I, unless I 
have missed any. And this should be the goal of the designers of this language, 
*regardless of the actual types*. Developers are olding their breath: please 
just make this happen.

Now Swift 3 may have an issue with $n parameters. Here is my suggestion, should 
`((Int, Int)) -> Int` be different from `(Int, Int) -> Int`:

f1 { $0 + $1 } // OK
f1 { $0.0 + $0.1 } // OK in Swift 3, compiler error in Swift 4?

f2 { $0 + $1 } // OK
f2 { $0.0 + $0.1 } // OK in Swift 3, compiler error in Swift 4?

f3 { $0 + $1 } // OK in Swift 3, compiler error in Swift 4?
f3 { $0.0 + $0.1 } // OK

f4 { $0 + $1 } // OK in Swift 3, compiler error in Swift 4?
f4 { $0.a + $0.b } // OK

Gwendal Roué

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
`((Int, Int)) -> Void` will be same type as `(Int, Int) -> Void`

2017-06-07 18:09 GMT+08:00 Adrian Zubarev :

> Keep in mind there is also SE–0111 cometary which promises sugar for
> parameter labels for closures:
>
> // **
> let foo(tuple:): ((Int, Int)) -> Void
>
> // Sugar for **
> let foo: (tuple: (Int, Int)) -> Void
>
> What will happen if you’d always flatten here?
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 7. Juni 2017 um 12:03:08, Adrian Zubarev (adrian.zubarev@devandartist.
> com) schrieb:
>
> Well please no:
>
> let fn2: ((Int, Int)) -> Void = { lhs, rhs in }
>
> Instead use destructuring sugar pitched by Chris Lattner on the other
> thread:
>
> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>
> That’s a correct error:
>
> let fn3: (Int, Int) -> Void = { _ in }
>
> This should be allowed, because we might want to work with the whole tuple
> and not a desctructured elements only:
>
> let fn4: ((Int, Int)) -> Void = { tuple in }
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
Replacement for fn4 is just make a tuple inside the closure

let workWithTuple: (Int, Int) -> Void = { doSomething(withTuple: ($0, $1)) }

2017-06-07 18:03 GMT+08:00 Adrian Zubarev :

> Well please no:
>
> let fn2: ((Int, Int)) -> Void = { lhs, rhs in }
>
> Instead use destructuring sugar pitched by Chris Lattner on the other
> thread:
>
> let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }
>
> That’s a correct error:
>
> let fn3: (Int, Int) -> Void = { _ in }
>
> This should be allowed, because we might want to work with the whole tuple
> and not a desctructured elements only:
>
> let fn4: ((Int, Int)) -> Void = { tuple in }
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution
Keep in mind there is also SE–0111 cometary which promises sugar for parameter 
labels for closures:

// **
let foo(tuple:): ((Int, Int)) -> Void

// Sugar for **
let foo: (tuple: (Int, Int)) -> Void
What will happen if you’d always flatten here?



-- 
Adrian Zubarev
Sent with Airmail

Am 7. Juni 2017 um 12:03:08, Adrian Zubarev (adrian.zuba...@devandartist.com) 
schrieb:

Well please no:


let fn2: ((Int, Int)) -> Void = { lhs, rhs in }

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }

That’s a correct error:

let fn3: (Int, Int) -> Void = { _ in }
This should be allowed, because we might want to work with the whole tuple and 
not a desctructured elements only:

let fn4: ((Int, Int)) -> Void = { tuple in }


-- 
Adrian Zubarev
Sent with Airmail
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Adrian Zubarev via swift-evolution
Well please no:


 let fn2: ((Int, Int)) -> Void = { lhs, rhs in }

Instead use destructuring sugar pitched by Chris Lattner on the other thread:

let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }

That’s a correct error:

let fn3: (Int, Int) -> Void = { _ in }
This should be allowed, because we might want to work with the whole tuple and 
not a desctructured elements only:

let fn4: ((Int, Int)) -> Void = { tuple in }


-- 
Adrian Zubarev
Sent with Airmail
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
Argument lists should or shouldn't be tuples. I think the question likes a
concept more than a technical question.

2017-06-07 14:56 GMT+08:00 Xiaodi Wu :

> On Wed, Jun 7, 2017 at 01:51 Susan Cheng  wrote:
>
>> I don't think it's a roll back change.
>>
>
> Function argument lists were once tuples, but they have not been for many
> years. All of the proposals I listed above proceed on the basis that these
> are not the same. Your proposal says that function argument lists should be
> tuples: that is rolling back a >5 year old change, is it not?
>
> The proposal is not proposing allow to reorder the parameters by using the
>> tuple or implicit tuple splat to fit the function parameters.
>> It's just clarify the relationship of tuples and argument lists.
>>
>> as the grammar of Swift 3, it's allowed wrapping the argument with a
>> single tuple to a function with two argument.
>>
>> [(1, 2)].map(+)
>>
>> and SE-0110 is the proposal make the distinguished and not allowed this
>> line of code.
>>
>> although we fix the compiler to accept the destructuring of tuples
>>
>> [(1, 2)].map({ ((lhs, rhs)) in lhs + rhs })
>>
>> it's not accepting the code of [(1, 2)].map(+) which the operator + are
>> not function with accepting the tuple of two elements.
>>
>> the only way we can thought is that the arguments with single tuple is
>> flattened and it's most compatible with Swift 3.
>>
>> 2017-06-07 13:05 GMT+08:00 Xiaodi Wu :
>>
>>> This is not what was meant during discussion about re-evaluating
>>> SE-0110. Tuples already behave as described, but function argument lists
>>> are not tuples and have not been for a very long time: see SE-0029, SE-0066.
>>>
>>> Also, consider SE-0046, which makes possible labels in single-argument
>>> argument lists (not possible in tuples), and SE-0060, which prohibits
>>> arbitrary reordering (although still possible in tuples). This is to say
>>> that the whole direction of Swift since version 2 has been to erase the
>>> historical relationship between tuples and argument lists.
>>>
>>> The question is how to accommodate some common use cases for
>>> destructuring as a matter of syntactic sugar after having carefully
>>> distinguished argument lists and tuples in the compiler, which is a given,
>>> not how to roll back a change that was settled in 2011, by Chris’s telling.
>>>
>>> On Tue, Jun 6, 2017 at 23:14 Susan Cheng via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>

 func add2(_ pair: (Int, Int)) -> Int {
 return pair.0 + pair.1
 }

 consider the follows

 let _add2 =  add2 // add2 have the typeof `((Int, Int)) -> Int`,
 it should flatten to `(Int, Int) -> Int`

 so these two lines are also acceptable
 [(1, 2)].map(add1)
 [(1, 2)].map(add2)

 this proposal is not just changing the behaviour of closure, this
 proposal also changing the tuple type

 (((Int, Int)))   flatten to   (Int, Int)
 (Int, (((Int, Int))), Int)   flatten to   (Int, (Int, Int), Int)


 2017-06-07 12:03 GMT+08:00 Stephen Celis :

> The inline cases make sense to me, but my concern for ambiguity are
> because we can define both of these functions:
>
> func add1(_ x: Int, _ y: Int) -> Int {
>   return x + y
> }
> func add2(_ pair: (Int, Int)) -> Int {
>   return pair.0 + pair.1
> }
>
> // What's the behavior here?
> [(1, 2)].map(add1)
> [(1, 2)].map(add2)
>
> What comes to mind, though, is, Swift already prevents single-element
> tuples, so why not prevent functions that take a single tuple as the only
> argument?
>
> Swift could provide a fix-it for functions that take single tuples and
> say: "Swift functions cannot take a single tuple. Please write a function
> that takes as many arguments as the tuple specified."
>
> Considering the fact that Swift generally operates in a multi-argument
> world, and given that functions taking a single tuple are the minority, I
> think this would be a good way to move forward.
>
> Stephen
>
> > On Jun 6, 2017, at 11:21 PM, Susan Cheng 
> wrote:
> >
> >  [(1, 2)].map({ x, y in x + y })  // this line is correct
> >  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should
> not accepted
> >
> > or
> >
> >  [(1, 2)].map({ $0 + $1 })  // this line is correct
> >  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
> >
> > it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) ->
> Int`
> > so, it should only accept the function with two arguments
> >
> >
> >
> > 2017-06-07 11:07 GMT+08:00 Stephen Celis :
> > I like this a lot, but how do we solve for the function case?
> 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Susan Cheng via swift-evolution
I don't think it's a roll back change.

The proposal is not proposing allow to reorder the parameters by using the
tuple or implicit tuple splat to fit the function parameters.
It's just clarify the relationship of tuples and argument lists.

as the grammar of Swift 3, it's allowed wrapping the argument with a single
tuple to a function with two argument.

[(1, 2)].map(+)

and SE-0110 is the proposal make the distinguished and not allowed this
line of code.

although we fix the compiler to accept the destructuring of tuples

[(1, 2)].map({ ((lhs, rhs)) in lhs + rhs })

it's not accepting the code of [(1, 2)].map(+) which the operator + are not
function with accepting the tuple of two elements.

the only way we can thought is that the arguments with single tuple is
flattened and it's most compatible with Swift 3.

2017-06-07 13:05 GMT+08:00 Xiaodi Wu :

> This is not what was meant during discussion about re-evaluating SE-0110.
> Tuples already behave as described, but function argument lists are not
> tuples and have not been for a very long time: see SE-0029, SE-0066.
>
> Also, consider SE-0046, which makes possible labels in single-argument
> argument lists (not possible in tuples), and SE-0060, which prohibits
> arbitrary reordering (although still possible in tuples). This is to say
> that the whole direction of Swift since version 2 has been to erase the
> historical relationship between tuples and argument lists.
>
> The question is how to accommodate some common use cases for destructuring
> as a matter of syntactic sugar after having carefully distinguished
> argument lists and tuples in the compiler, which is a given, not how to
> roll back a change that was settled in 2011, by Chris’s telling.
>
> On Tue, Jun 6, 2017 at 23:14 Susan Cheng via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> func add2(_ pair: (Int, Int)) -> Int {
>> return pair.0 + pair.1
>> }
>>
>> consider the follows
>>
>> let _add2 =  add2 // add2 have the typeof `((Int, Int)) -> Int`, it
>> should flatten to `(Int, Int) -> Int`
>>
>> so these two lines are also acceptable
>> [(1, 2)].map(add1)
>> [(1, 2)].map(add2)
>>
>> this proposal is not just changing the behaviour of closure, this
>> proposal also changing the tuple type
>>
>> (((Int, Int)))   flatten to   (Int, Int)
>> (Int, (((Int, Int))), Int)   flatten to   (Int, (Int, Int), Int)
>>
>>
>> 2017-06-07 12:03 GMT+08:00 Stephen Celis :
>>
>>> The inline cases make sense to me, but my concern for ambiguity are
>>> because we can define both of these functions:
>>>
>>> func add1(_ x: Int, _ y: Int) -> Int {
>>>   return x + y
>>> }
>>> func add2(_ pair: (Int, Int)) -> Int {
>>>   return pair.0 + pair.1
>>> }
>>>
>>> // What's the behavior here?
>>> [(1, 2)].map(add1)
>>> [(1, 2)].map(add2)
>>>
>>> What comes to mind, though, is, Swift already prevents single-element
>>> tuples, so why not prevent functions that take a single tuple as the only
>>> argument?
>>>
>>> Swift could provide a fix-it for functions that take single tuples and
>>> say: "Swift functions cannot take a single tuple. Please write a function
>>> that takes as many arguments as the tuple specified."
>>>
>>> Considering the fact that Swift generally operates in a multi-argument
>>> world, and given that functions taking a single tuple are the minority, I
>>> think this would be a good way to move forward.
>>>
>>> Stephen
>>>
>>> > On Jun 6, 2017, at 11:21 PM, Susan Cheng 
>>> wrote:
>>> >
>>> >  [(1, 2)].map({ x, y in x + y })  // this line is correct
>>> >  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should not
>>> accepted
>>> >
>>> > or
>>> >
>>> >  [(1, 2)].map({ $0 + $1 })  // this line is correct
>>> >  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
>>> >
>>> > it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) ->
>>> Int`
>>> > so, it should only accept the function with two arguments
>>> >
>>> >
>>> >
>>> > 2017-06-07 11:07 GMT+08:00 Stephen Celis :
>>> > I like this a lot, but how do we solve for the function case?
>>> >
>>> > func add(_ x: Int, _ y: Int) -> Int {
>>> >   return x + y
>>> > }
>>> > [(1, 2)].map(add)
>>> >
>>> > Where does `map` with a function of `((Int, Int)) -> Int` fit in?
>>> >
>>> > > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>> > >
>>> > > Introduction
>>> > >
>>> > >
>>> > > Because the painful of SE-0110, here is a proposal to clarify the
>>> tuple syntax.
>>> > >
>>> > > Proposed solution
>>> > >
>>> > > 1. single element tuple always be flattened
>>> > >
>>> > > let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>>> > >
>>> > > let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int,
>>> Int)
>>> > >
>>> > > 2. function arguments list also consider as a tuple, which means the
>>> function that 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 01:51 Susan Cheng  wrote:

> I don't think it's a roll back change.
>

Function argument lists were once tuples, but they have not been for many
years. All of the proposals I listed above proceed on the basis that these
are not the same. Your proposal says that function argument lists should be
tuples: that is rolling back a >5 year old change, is it not?

The proposal is not proposing allow to reorder the parameters by using the
> tuple or implicit tuple splat to fit the function parameters.
> It's just clarify the relationship of tuples and argument lists.
>
> as the grammar of Swift 3, it's allowed wrapping the argument with a
> single tuple to a function with two argument.
>
> [(1, 2)].map(+)
>
> and SE-0110 is the proposal make the distinguished and not allowed this
> line of code.
>
> although we fix the compiler to accept the destructuring of tuples
>
> [(1, 2)].map({ ((lhs, rhs)) in lhs + rhs })
>
> it's not accepting the code of [(1, 2)].map(+) which the operator + are
> not function with accepting the tuple of two elements.
>
> the only way we can thought is that the arguments with single tuple is
> flattened and it's most compatible with Swift 3.
>
> 2017-06-07 13:05 GMT+08:00 Xiaodi Wu :
>
>> This is not what was meant during discussion about re-evaluating SE-0110.
>> Tuples already behave as described, but function argument lists are not
>> tuples and have not been for a very long time: see SE-0029, SE-0066.
>>
>> Also, consider SE-0046, which makes possible labels in single-argument
>> argument lists (not possible in tuples), and SE-0060, which prohibits
>> arbitrary reordering (although still possible in tuples). This is to say
>> that the whole direction of Swift since version 2 has been to erase the
>> historical relationship between tuples and argument lists.
>>
>> The question is how to accommodate some common use cases for
>> destructuring as a matter of syntactic sugar after having carefully
>> distinguished argument lists and tuples in the compiler, which is a given,
>> not how to roll back a change that was settled in 2011, by Chris’s telling.
>>
>> On Tue, Jun 6, 2017 at 23:14 Susan Cheng via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> func add2(_ pair: (Int, Int)) -> Int {
>>> return pair.0 + pair.1
>>> }
>>>
>>> consider the follows
>>>
>>> let _add2 =  add2 // add2 have the typeof `((Int, Int)) -> Int`, it
>>> should flatten to `(Int, Int) -> Int`
>>>
>>> so these two lines are also acceptable
>>> [(1, 2)].map(add1)
>>> [(1, 2)].map(add2)
>>>
>>> this proposal is not just changing the behaviour of closure, this
>>> proposal also changing the tuple type
>>>
>>> (((Int, Int)))   flatten to   (Int, Int)
>>> (Int, (((Int, Int))), Int)   flatten to   (Int, (Int, Int), Int)
>>>
>>>
>>> 2017-06-07 12:03 GMT+08:00 Stephen Celis :
>>>
 The inline cases make sense to me, but my concern for ambiguity are
 because we can define both of these functions:

 func add1(_ x: Int, _ y: Int) -> Int {
   return x + y
 }
 func add2(_ pair: (Int, Int)) -> Int {
   return pair.0 + pair.1
 }

 // What's the behavior here?
 [(1, 2)].map(add1)
 [(1, 2)].map(add2)

 What comes to mind, though, is, Swift already prevents single-element
 tuples, so why not prevent functions that take a single tuple as the only
 argument?

 Swift could provide a fix-it for functions that take single tuples and
 say: "Swift functions cannot take a single tuple. Please write a function
 that takes as many arguments as the tuple specified."

 Considering the fact that Swift generally operates in a multi-argument
 world, and given that functions taking a single tuple are the minority, I
 think this would be a good way to move forward.

 Stephen

 > On Jun 6, 2017, at 11:21 PM, Susan Cheng 
 wrote:
 >
 >  [(1, 2)].map({ x, y in x + y })  // this line is correct
 >  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should
 not accepted
 >
 > or
 >
 >  [(1, 2)].map({ $0 + $1 })  // this line is correct
 >  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
 >
 > it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) ->
 Int`
 > so, it should only accept the function with two arguments
 >
 >
 >
 > 2017-06-07 11:07 GMT+08:00 Stephen Celis :
 > I like this a lot, but how do we solve for the function case?
 >
 > func add(_ x: Int, _ y: Int) -> Int {
 >   return x + y
 > }
 > [(1, 2)].map(add)
 >
 > Where does `map` with a function of `((Int, Int)) -> Int` fit in?
 >
 > > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution <
 

Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-07 Thread Xiaodi Wu via swift-evolution
On Wed, Jun 7, 2017 at 00:39 Stephen Celis  wrote:

> > On Jun 7, 2017, at 1:05 AM, Xiaodi Wu  wrote:
> >
> > This is not what was meant during discussion about re-evaluating
> SE-0110. Tuples already behave as described, but function argument lists
> are not tuples and have not been for a very long time: see SE-0029, SE-0066.
> >
> > Also, consider SE-0046, which makes possible labels in single-argument
> argument lists (not possible in tuples), and SE-0060, which prohibits
> arbitrary reordering (although still possible in tuples). This is to say
> that the whole direction of Swift since version 2 has been to erase the
> historical relationship between tuples and argument lists.
> >
> > The question is how to accommodate some common use cases for
> destructuring as a matter of syntactic sugar after having carefully
> distinguished argument lists and tuples in the compiler, which is a given,
> not how to roll back a change that was settled in 2011, by Chris’s telling.
>
> As one of many who is directly affected and wants resolution, I think the
> discussion of re-evaluating SE-0110 most certainly expands to these earlier
> decisions. While Swift has moved in the direction of distinguishing tuples
> and argument lists in decidedly different ways, I think it's perfectly
> valid to consider the alternative: a simpler and equally-valid solution:
> flattened tuples that are isomorphic to argument lists.


This is an issue that’s coming up on this list with alarming frequency:
meta-debates on what is even in scope for consideration. Reversing five or
six proposals as well as a decision taken prior to Swift 2 is certainly not
“perfectly valid.” Simply, the ship has long sailed.

Argument labels certainly complicate semantics, but we still erase tuple
> labels in general use to this day. Meanwhile, prohibited arbitrary
> reordering remains complicated (I just recently worked with an SPM module
> that advertised instructions the compiler disallowed, and it took awhile to
> find the correct, compiler-allowed ordering while troubleshooting
> confusing, compiler-driven error messaging).


Those are enums, which were aligned with argument lists instead of tuples
in yet another proposal, SE-0155.

All of these hiccups are the result of compiler optimizations and
> simplifications that hinder end-user ergonomics.


Having the compiler perform reliably is the most basic of user ergonomics,
wouldn’t you say?

Again: while I can appreciate making the compiler as simple and strict as
> possible, the end-user and end-use cases suffer along the way.
>
> Stephen
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Stephen Celis via swift-evolution
> On Jun 7, 2017, at 1:05 AM, Xiaodi Wu  wrote:
> 
> This is not what was meant during discussion about re-evaluating SE-0110. 
> Tuples already behave as described, but function argument lists are not 
> tuples and have not been for a very long time: see SE-0029, SE-0066.
> 
> Also, consider SE-0046, which makes possible labels in single-argument 
> argument lists (not possible in tuples), and SE-0060, which prohibits 
> arbitrary reordering (although still possible in tuples). This is to say that 
> the whole direction of Swift since version 2 has been to erase the historical 
> relationship between tuples and argument lists.
> 
> The question is how to accommodate some common use cases for destructuring as 
> a matter of syntactic sugar after having carefully distinguished argument 
> lists and tuples in the compiler, which is a given, not how to roll back a 
> change that was settled in 2011, by Chris’s telling.

As one of many who is directly affected and wants resolution, I think the 
discussion of re-evaluating SE-0110 most certainly expands to these earlier 
decisions. While Swift has moved in the direction of distinguishing tuples and 
argument lists in decidedly different ways, I think it's perfectly valid to 
consider the alternative: a simpler and equally-valid solution: flattened 
tuples that are isomorphic to argument lists.

Argument labels certainly complicate semantics, but we still erase tuple labels 
in general use to this day. Meanwhile, prohibited arbitrary reordering remains 
complicated (I just recently worked with an SPM module that advertised 
instructions the compiler disallowed, and it took awhile to find the correct, 
compiler-allowed ordering while troubleshooting confusing, compiler-driven 
error messaging).

All of these hiccups are the result of compiler optimizations and 
simplifications that hinder end-user ergonomics.

Again: while I can appreciate making the compiler as simple and strict as 
possible, the end-user and end-use cases suffer along the way.

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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Xiaodi Wu via swift-evolution
This is not what was meant during discussion about re-evaluating SE-0110.
Tuples already behave as described, but function argument lists are not
tuples and have not been for a very long time: see SE-0029, SE-0066.

Also, consider SE-0046, which makes possible labels in single-argument
argument lists (not possible in tuples), and SE-0060, which prohibits
arbitrary reordering (although still possible in tuples). This is to say
that the whole direction of Swift since version 2 has been to erase the
historical relationship between tuples and argument lists.

The question is how to accommodate some common use cases for destructuring
as a matter of syntactic sugar after having carefully distinguished
argument lists and tuples in the compiler, which is a given, not how to
roll back a change that was settled in 2011, by Chris’s telling.
On Tue, Jun 6, 2017 at 23:14 Susan Cheng via swift-evolution <
swift-evolution@swift.org> wrote:

>
> func add2(_ pair: (Int, Int)) -> Int {
> return pair.0 + pair.1
> }
>
> consider the follows
>
> let _add2 =  add2 // add2 have the typeof `((Int, Int)) -> Int`, it
> should flatten to `(Int, Int) -> Int`
>
> so these two lines are also acceptable
> [(1, 2)].map(add1)
> [(1, 2)].map(add2)
>
> this proposal is not just changing the behaviour of closure, this proposal
> also changing the tuple type
>
> (((Int, Int)))   flatten to   (Int, Int)
> (Int, (((Int, Int))), Int)   flatten to   (Int, (Int, Int), Int)
>
>
> 2017-06-07 12:03 GMT+08:00 Stephen Celis :
>
>> The inline cases make sense to me, but my concern for ambiguity are
>> because we can define both of these functions:
>>
>> func add1(_ x: Int, _ y: Int) -> Int {
>>   return x + y
>> }
>> func add2(_ pair: (Int, Int)) -> Int {
>>   return pair.0 + pair.1
>> }
>>
>> // What's the behavior here?
>> [(1, 2)].map(add1)
>> [(1, 2)].map(add2)
>>
>> What comes to mind, though, is, Swift already prevents single-element
>> tuples, so why not prevent functions that take a single tuple as the only
>> argument?
>>
>> Swift could provide a fix-it for functions that take single tuples and
>> say: "Swift functions cannot take a single tuple. Please write a function
>> that takes as many arguments as the tuple specified."
>>
>> Considering the fact that Swift generally operates in a multi-argument
>> world, and given that functions taking a single tuple are the minority, I
>> think this would be a good way to move forward.
>>
>> Stephen
>>
>> > On Jun 6, 2017, at 11:21 PM, Susan Cheng 
>> wrote:
>> >
>> >  [(1, 2)].map({ x, y in x + y })  // this line is correct
>> >  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should not
>> accepted
>> >
>> > or
>> >
>> >  [(1, 2)].map({ $0 + $1 })  // this line is correct
>> >  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
>> >
>> > it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) -> Int`
>> > so, it should only accept the function with two arguments
>> >
>> >
>> >
>> > 2017-06-07 11:07 GMT+08:00 Stephen Celis :
>> > I like this a lot, but how do we solve for the function case?
>> >
>> > func add(_ x: Int, _ y: Int) -> Int {
>> >   return x + y
>> > }
>> > [(1, 2)].map(add)
>> >
>> > Where does `map` with a function of `((Int, Int)) -> Int` fit in?
>> >
>> > > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> > >
>> > > Introduction
>> > >
>> > >
>> > > Because the painful of SE-0110, here is a proposal to clarify the
>> tuple syntax.
>> > >
>> > > Proposed solution
>> > >
>> > > 1. single element tuple always be flattened
>> > >
>> > > let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>> > >
>> > > let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
>> > >
>> > > 2. function arguments list also consider as a tuple, which means the
>> function that accept a single tuple should always be flattened.
>> > >
>> > > let fn1: (Int, Int) -> Void = { _, _ in }
>> > >
>> > > let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
>> > >
>> > > let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
>> arguments
>> > >
>> > > let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are
>> two arguments
>> > >
>> > > ___
>> > > 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
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Susan Cheng via swift-evolution
func add2(_ pair: (Int, Int)) -> Int {
return pair.0 + pair.1
}

consider the follows

let _add2 =  add2 // add2 have the typeof `((Int, Int)) -> Int`, it
should flatten to `(Int, Int) -> Int`

so these two lines are also acceptable
[(1, 2)].map(add1)
[(1, 2)].map(add2)

this proposal is not just changing the behaviour of closure, this proposal
also changing the tuple type

(((Int, Int)))   flatten to   (Int, Int)
(Int, (((Int, Int))), Int)   flatten to   (Int, (Int, Int), Int)


2017-06-07 12:03 GMT+08:00 Stephen Celis :

> The inline cases make sense to me, but my concern for ambiguity are
> because we can define both of these functions:
>
> func add1(_ x: Int, _ y: Int) -> Int {
>   return x + y
> }
> func add2(_ pair: (Int, Int)) -> Int {
>   return pair.0 + pair.1
> }
>
> // What's the behavior here?
> [(1, 2)].map(add1)
> [(1, 2)].map(add2)
>
> What comes to mind, though, is, Swift already prevents single-element
> tuples, so why not prevent functions that take a single tuple as the only
> argument?
>
> Swift could provide a fix-it for functions that take single tuples and
> say: "Swift functions cannot take a single tuple. Please write a function
> that takes as many arguments as the tuple specified."
>
> Considering the fact that Swift generally operates in a multi-argument
> world, and given that functions taking a single tuple are the minority, I
> think this would be a good way to move forward.
>
> Stephen
>
> > On Jun 6, 2017, at 11:21 PM, Susan Cheng  wrote:
> >
> >  [(1, 2)].map({ x, y in x + y })  // this line is correct
> >  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should not
> accepted
> >
> > or
> >
> >  [(1, 2)].map({ $0 + $1 })  // this line is correct
> >  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
> >
> > it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) -> Int`
> > so, it should only accept the function with two arguments
> >
> >
> >
> > 2017-06-07 11:07 GMT+08:00 Stephen Celis :
> > I like this a lot, but how do we solve for the function case?
> >
> > func add(_ x: Int, _ y: Int) -> Int {
> >   return x + y
> > }
> > [(1, 2)].map(add)
> >
> > Where does `map` with a function of `((Int, Int)) -> Int` fit in?
> >
> > > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution <
> swift-evolution@swift.org> wrote:
> > >
> > > Introduction
> > >
> > >
> > > Because the painful of SE-0110, here is a proposal to clarify the
> tuple syntax.
> > >
> > > Proposed solution
> > >
> > > 1. single element tuple always be flattened
> > >
> > > let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
> > >
> > > let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
> > >
> > > 2. function arguments list also consider as a tuple, which means the
> function that accept a single tuple should always be flattened.
> > >
> > > let fn1: (Int, Int) -> Void = { _, _ in }
> > >
> > > let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
> > >
> > > let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
> arguments
> > >
> > > let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
> arguments
> > >
> > > ___
> > > 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Stephen Celis via swift-evolution
The inline cases make sense to me, but my concern for ambiguity are because we 
can define both of these functions:

func add1(_ x: Int, _ y: Int) -> Int {
  return x + y
}
func add2(_ pair: (Int, Int)) -> Int {
  return pair.0 + pair.1
}

// What's the behavior here?
[(1, 2)].map(add1)
[(1, 2)].map(add2)

What comes to mind, though, is, Swift already prevents single-element tuples, 
so why not prevent functions that take a single tuple as the only argument?

Swift could provide a fix-it for functions that take single tuples and say: 
"Swift functions cannot take a single tuple. Please write a function that takes 
as many arguments as the tuple specified."

Considering the fact that Swift generally operates in a multi-argument world, 
and given that functions taking a single tuple are the minority, I think this 
would be a good way to move forward.

Stephen

> On Jun 6, 2017, at 11:21 PM, Susan Cheng  wrote:
> 
>  [(1, 2)].map({ x, y in x + y })  // this line is correct
>  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should not 
> accepted
> 
> or
> 
>  [(1, 2)].map({ $0 + $1 })  // this line is correct
>  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
> 
> it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) -> Int`
> so, it should only accept the function with two arguments
> 
> 
> 
> 2017-06-07 11:07 GMT+08:00 Stephen Celis :
> I like this a lot, but how do we solve for the function case?
> 
> func add(_ x: Int, _ y: Int) -> Int {
>   return x + y
> }
> [(1, 2)].map(add)
> 
> Where does `map` with a function of `((Int, Int)) -> Int` fit in?
> 
> > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution 
> >  wrote:
> >
> > Introduction
> >
> >
> > Because the painful of SE-0110, here is a proposal to clarify the tuple 
> > syntax.
> >
> > Proposed solution
> >
> > 1. single element tuple always be flattened
> >
> > let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
> >
> > let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
> >
> > 2. function arguments list also consider as a tuple, which means the 
> > function that accept a single tuple should always be flattened.
> >
> > let fn1: (Int, Int) -> Void = { _, _ in }
> >
> > let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
> >
> > let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two 
> > arguments
> >
> > let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two 
> > arguments
> >
> > ___
> > 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Susan Cheng via swift-evolution
a PR is create: https://github.com/apple/swift-evolution/pull/722

2017-06-07 10:15 GMT+08:00 Susan Cheng :

> Introduction
>
> Because the painful of SE-0110, here is a proposal to clarify the tuple
> syntax.
>
> Proposed solution
> 1. single element tuple always be flattened
>
> let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>
>
> let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
>
> 2. function arguments list also consider as a tuple, which means the
> function that accept a single tuple should always be flattened.
>
> let fn1: (Int, Int) -> Void = { _, _ in }
>
>
> let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
>
> let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
> arguments
>
> let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
> arguments
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Stephen Celis via swift-evolution
I like this a lot, but how do we solve for the function case?

func add(_ x: Int, _ y: Int) -> Int {
  return x + y
}
[(1, 2)].map(add)

Where does `map` with a function of `((Int, Int)) -> Int` fit in?

> On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution 
>  wrote:
> 
> Introduction
> 
> 
> Because the painful of SE-0110, here is a proposal to clarify the tuple 
> syntax.
> 
> Proposed solution
> 
> 1. single element tuple always be flattened
> 
> let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
> 
> let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
> 
> 2. function arguments list also consider as a tuple, which means the function 
> that accept a single tuple should always be flattened.
> 
> let fn1: (Int, Int) -> Void = { _, _ in }
> 
> let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
> 
> let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two arguments
> 
> let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two 
> arguments
> 
> ___
> 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Susan Cheng via swift-evolution
 [(1, 2)].map({ x, y in x + y })  // this line is correct
 [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should not
accepted

or

 [(1, 2)].map({ $0 + $1 })  // this line is correct
 [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted

it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) -> Int`
so, it should only accept the function with two arguments



2017-06-07 11:07 GMT+08:00 Stephen Celis :

> I like this a lot, but how do we solve for the function case?
>
> func add(_ x: Int, _ y: Int) -> Int {
>   return x + y
> }
> [(1, 2)].map(add)
>
> Where does `map` with a function of `((Int, Int)) -> Int` fit in?
>
> > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > Introduction
> >
> >
> > Because the painful of SE-0110, here is a proposal to clarify the tuple
> syntax.
> >
> > Proposed solution
> >
> > 1. single element tuple always be flattened
> >
> > let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
> >
> > let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
> >
> > 2. function arguments list also consider as a tuple, which means the
> function that accept a single tuple should always be flattened.
> >
> > let fn1: (Int, Int) -> Void = { _, _ in }
> >
> > let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
> >
> > let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
> arguments
> >
> > let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
> arguments
> >
> > ___
> > 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


Re: [swift-evolution] Proposal: Always flatten the single element tuple

2017-06-06 Thread Susan Cheng via swift-evolution
it's also clear that these code will never be ambiguous

 [(1, 2)].map({ $0 }) // $0 always not a tuple, because arguments should be
flattened

2017-06-07 11:21 GMT+08:00 Susan Cheng :

>  [(1, 2)].map({ x, y in x + y })  // this line is correct
>  [(1, 2)].map({ tuple in tuple.0 + tuple.1 })  // this line should not
> accepted
>
> or
>
>  [(1, 2)].map({ $0 + $1 })  // this line is correct
>  [(1, 2)].map({ $0.0 + $0.1 })  // this line should not accepted
>
> it's because `((Int, Int)) -> Int` always flatten to `(Int, Int) -> Int`
> so, it should only accept the function with two arguments
>
>
>
> 2017-06-07 11:07 GMT+08:00 Stephen Celis :
>
>> I like this a lot, but how do we solve for the function case?
>>
>> func add(_ x: Int, _ y: Int) -> Int {
>>   return x + y
>> }
>> [(1, 2)].map(add)
>>
>> Where does `map` with a function of `((Int, Int)) -> Int` fit in?
>>
>> > On Jun 6, 2017, at 10:15 PM, Susan Cheng via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >
>> > Introduction
>> >
>> >
>> > Because the painful of SE-0110, here is a proposal to clarify the tuple
>> syntax.
>> >
>> > Proposed solution
>> >
>> > 1. single element tuple always be flattened
>> >
>> > let tuple1: (((Int))) = 0  // TypeOf(tuple1) == Int
>> >
>> > let tuple2: Int))), Int) = (0, 0)  // TypeOf(tuple2) == (Int, Int)
>> >
>> > 2. function arguments list also consider as a tuple, which means the
>> function that accept a single tuple should always be flattened.
>> >
>> > let fn1: (Int, Int) -> Void = { _, _ in }
>> >
>> > let fn2: ((Int, Int)) -> Void = { _, _ in }  // always flattened
>> >
>> > let fn3: (Int, Int) -> Void = { _ in }  // not allowed, here are two
>> arguments
>> >
>> > let fn4: ((Int, Int)) -> Void = { _ in }  // not allowed, here are two
>> arguments
>> >
>> > ___
>> > 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