问题
Update at 2016.09.19
There is a tricky, indirect way to use variadic parameters before some other parameters in closure expression parameters list, haha
let testClosure = { (scores: Int...) -> (_ name: String) -> String in
return { name in
return "Happy"
}
}
let k = testClosure(1, 2, 3)("John")
And I found some related issues in bugs.swift.org: SR-2475 SR-494
Original Post
According to the document of Swift 3.0, for a closure expression, "variadic parameters can be used if you name the variadic parameter"(see Closure Expresssion Syntax part). But for Swift 2.x, the description is "Variadic parameters can be used if you name the variadic parameter and place it last in the parameter list", the border part has been removed in Swift 3.0 document, is it means variadic parameter can be a argument of closure expression even it is not at the last place? If so, why the codes below can't compile successfully?
let testClosure = { (scores: Int..., name: String) -> String in
return "Happy"
}
let k = testClosure(1, 2, 3, "John") // Missing argument for parameter #2 in call
If the argument label can be used in the call, I think the compiler can compile the code above successfully, but in Swift 3.0, closure expression's argument labels are regarded as Extraneous.
Besides, Swift 3.0 document indicates that the parameters in closure expression syntax can be in-out parameters, but Swift 3.0 said that closure expression syntax can use constant parameters, variable parameters, and inout parameters. Why Apple removed descriptions like constant parameters, variable paramters, is it because in Swift 3.0, the parameters can't be var
?
Thank you very much for your help!
回答1:
Still in Swift3 variadic arguments have to be the last parameter in the signature, because despite the fact that in your case the last parameter typed as String
can be deduced, there's some cases where not, because of the infinite expansion of variadic argument:
let foo = { (i:Int..., j: Int) -> Int in
return j
}
foo(1,2)
...in Swift 3.0, the parameters can't be var?
var
params where removed in Swift3 SE-0003 to avoid confusion with inout
parameters, because both var
and inout
params can be assigned inside function, but just inout
is reflected back.
func doSomethingWithVar(var i: Int) {
i = 2 // change visible inside function.
}
func doSomethingWithInout(inout i: Int) {
i = 2 // change reflected back to caller.
}
removing var
from parameter list, remove the confusion above.
回答2:
Variadic parameter have to be last and according to your situation, you can type this:
let testClosure = { (_ name: String, scores: Int...) -> String in
return "Happy"
}
let k = testClosure("John", 1, 2, 3)
回答3:
You are able to create a func in Swift 3.0 where the variadic parameter is NOT the last argument. For example...
func addButtons(buttons: UIButton..., completion: (() -> ())? = nil)
I believe it's because the parameter following the variadic parameter is named, and so the func does not confuse the next named argument with more variadic arguments.
addButtons(buttons: button1, button2, button3) {
//do completion stuff
}
来源:https://stackoverflow.com/questions/39548852/swift-3-0-closure-expression-what-if-the-variadic-parameters-not-at-the-last-pl