Swift 3.0 closure expression: what if the variadic parameters not at the last place in the parameters list?

旧街凉风 提交于 2019-12-23 00:53:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!