John and others, who are involved into this thread.
I'd suggest to clarify the current(Swift4) situation with function/closure type before we make any other decision and before continue to discuss the subject. (sorry for long email, but I feel the problem with SE-0110 is wider than just "let's just drop it")

Please review this code and its result (swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-01-a-osx) :

func fooParam(_ x: Int, _ y: Int){}
func fooTuple(_ x: (Int, Int)) {}

print("type of fooParam is", type(of:fooParam))
// type of fooParam is (Int, Int) -> ()

print("type of fooTuple is", type(of:fooTuple))
// type of fooTuple is (Int, Int) -> ()

print("type of fooParam == type of fooTuple ?", type(of: fooParam) == type(of: fooTuple))
// true

if fooParam is (Int,Int)->() { print("fooParam is (Int,Int)->()") }
// fooParam is (Int,Int)->()

if fooParam is ((Int,Int))->() { print("fooParam is ((Int,Int))->()") }
// fooParam is ((Int,Int))->()

if fooTuple is (Int,Int)->() { print("fooTuple is (Int,Int)->()") }
// fooTuple is (Int,Int)->()

if fooTuple is ((Int,Int))->() { print("fooTuple is ((Int,Int))->()") }
// fooTuple is ((Int,Int))->()


var closureParam = { (x: Int, y: Int) in  }
var closureTuple = { (x: (Int, Int)) in  }

print("type of closureParam is", type(of:closureParam))
// type of closureParam is (Int, Int) -> ()

print("type of closureTuple is", type(of:closureTuple))
// type of closureTuple is (Int, Int) -> ()

if closureParam is (Int,Int)->() { print("closureParam is (Int,Int)->()") }
// closureParam is (Int,Int)->()

if closureParam is ((Int,Int))->() { print("closureParam is ((Int,Int))->()") }
// closureParam is ((Int,Int))->()

if closureTuple is (Int,Int)->() { print("closureTuple is (Int,Int)->()") }
// closureTuple is (Int,Int)->()

if closureTuple is ((Int,Int))->() { print("closureTuple is ((Int,Int))->()") }
// closureTuple is ((Int,Int))->()


func barParams(_ callback: (Int,Int)->()) { callback(1,2) }

//barParams(fooTuple)
//error: cannot convert value of type '((Int, Int)) -> ()' to expected argument type '(Int, Int) -> ()'

//barParams(closureTuple)
//error: cannot convert value of type '((Int, Int)) -> ()' to expected argument type '(Int, Int) -> ()'

func barTuple(_ callback: ((Int,Int))->()) { let tuple = (1,2); callback(tuple) 
}

//barTuple(fooParam)
//error: nested tuple parameter '(Int, Int)' of function '(((Int, Int)) -> ()) -> ()' does not support destructuring

//barTuple(closureParam)
//error: cannot convert value of type '(Int, Int) -> ()' to expected argument type '((Int, Int)) -> ()'


So, what is the type of fooParam/fooTuple/closureParam/closureTuple ?
Why the type is different in different situations?
Should we have strong and unambiguous type for functions/closures and probably *then* allow implicit conversion like "(Int,Int)->() can be used when ((Int,Int))->() is required and vise-versa"?

We have all this inconsistency with function/closure types from Swift 2, and this should be actually fixed in Swift 3, but still we are going to keep that in Swift 4.

Personally, I'm not against tuple deconstructing in closures and even think we can just have allowed implicit conversion between func/closure with single tuple argument and a list of arguments. But, I do believe we need consistent state in this area, strong types and clear rules. Because of this, if we have no time to implement good solution/workaround for Swift 4, I believe it is better to keep/fully implement SE-0110 and then provide solution for tuple destructuring. Otherwise we are going to have all these mess with func/closure types for very long time after Swift 4. Or we can try to implement a good workaround before release.

In current Swift 4 we are allowed for this:
.filter {(arg: (name: String, age: Int)) in arg.age >= 18 }

Is it really no way(before Swift 4 is released) to allow type inference for 'name' and 'age'? I believe this could be a good *workaround*, totally in Swift way(just like you can omit types for arguments in closure, or can specify them), this will keep the existed syntax for closure arguments and this will not prevent us from suggesting best solution after the Swift 4 release. And IMO this is acceptable compromise between loosing tuple deconstruction and keep the mess with function/closure type:
.filter {(arg: (name, age)) in arg.age >= 18 }

Or, as I said, just allow implicit conversion between function/closure types taking one tuple argument and a list of arguments. But still .filter should expect exactly ((Int,String))->() but it is allowed to send (Int,String)->() to it. All is strongly typed, but with magic "conversion".

I still believe that SE-0066 was the proposal that answered all these questions and said that (Int,Int)->() and ((Int,Int))->() are two different types. SE-0110 just clarified that the same rule should be applied to closures. Until we started to discuss revisiting of SE-0110 I was under strong impression that SE-0066 was just partially implemented in Swift 3 and will be fully implemented only in Swift 4.

I even believe that information on SE-0066 page is not correct, that SE was NOT fully implemented for Swift 3 as described in the proposal header on site. Could someone from core team please clarify, if they really think that proposal is fully implemented in current Swift 4.0 build?

I even ask(please, when you have a moment) Chris Lattner to look into this thread, because of his words in Rationale part of the SE-0110 acceptance message:

"... The community and core team agree that this proposal is the right thing to do, and many agree that this could probably have been treated as a bug fix on a previous proposal.
..."
(https://lists.swift.org/pipermail/swift-evolution-announce/2016-July/000215.html)

Seems like Chris at that moment also was thinking about SE-0110 just as bug fix for SE-0066/SE-0029 and so probably he can provide some useful information/thoughts about the subject.

Thank you for attention.
Vladimir.

On 02.06.2017 1:06, John McCall wrote:

On Jun 1, 2017, at 2:39 PM, Pavol Vaskovic <p...@pali.sk <mailto:p...@pali.sk>> 
wrote:

On Thu, Jun 1, 2017 at 8:52 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:


    I understand that there are developers who dislike SE-0110's impact on 
certain
    kinds of functional programming, but that is a very broad complaint that is
unlikely to reach consensus or acceptance, especially for Swift 4.

The impact of SE-0110 as currently implemented in Swift 4 leads to following migration choice wherever you have a closure that takes tuple argument:
* concise but obfuscate code ($0.1, ...)
* readable but verbose code (requiring a ton of boilerplate: intermediate argument, expand signature to include return type, desctructure tuple on new line using let, add return clause)

Maybe I misunderstood you, but I don't think this is marginal issue affecting only some "developers that dislike the impact on certain kinds of functional programming".

You're misunderstanding me. I have explicitly said, several times, that I agree that the impact on tuple destructuring in closures is a serious regression. There have *also* been objections to losing argument-splat behavior, and while that does negatively affect some functional styles, I think it would be a mistake to try to address that now.

John.


This is a HUGE regression to the usability of all closure with tuple arguments. I'd wager that is the prevailing consensual opinion of anyone who has experienced this issue in practice.

I would go as far as to claim that current implementation of SE-0110 does not conform to the Swift 4's goal of backwards source compatibility.

    In contrast, I think we may be able to gain consensus on a more targeted
    proposal that just re-admits tuple destructuring in closures, assuming we 
can
    find an acceptable implementation.


From what I understand our options are quite limited because of tight constraints of Swift 4's emphasis on backwards source-compatibility and impending release deadline:

* effectively revert SE-0110 by always using the codepath for Swift 3 compatibility mode * implement full tuple destructuring (unexplored issues with syntax and backwards compatibility)

(Note that Swift 3 didn't support full tuple destructuring - SR-4738 <https://bugs.swift.org/browse/SR-4738>)

--Pavol

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

Reply via email to