问题
I just found out there's an implicit cast :
From function taking n parameters (A, B, ...) -> R
To function taking a n-tuple ((A, B, ...)) -> R
Example n°1
func withTuple(_ a: (Int, Int)) { }
func withoutTuple(_ a: Int, _ b: Int) { }
func call(tupleFunction: ((Int, Int)) -> ()) {
tupleFunction((1, 2))
}
call(tupleFunction: withTuple)
call(tupleFunction: withoutTuple) // Magic here
(Valid Swift 4.2 code)
Example n°2
[(1, 2), (3, 3)].map(*) // Magic here
Is this behaviour documented somewhere?
回答1:
Before Swift 3, one was able to call a function either by explicitly specifying its arguments, or by passing a well-crafted tuple. However this way of calling functions was removed when SE-0029 was implemented.
Basically, the following was possible:
func buildDescription(name: String, age: Int) -> String {
return "Hi, I am \(name), and I am \(age)"
}
buildDescription("John Doe", age: 21)
// or, via a tuple, giving the same result
buildDescription(("John Doe", name: 21))
The Swift forums have this post regarding the above change (emphasis mine):
The proposal has been accepted for Swift 3. We acknowledge that we're removing a useful feature without providing an equally expressive drop-in replacement. However, maintaining this behavior in the type checker is a severe source of implementation complexity, and actively interferes with our plans to solidify the type system.
So it looks like the call-function-by-tuple support was prohibited only at the type checker level, meaning you cannot directly pass tuples to functions, however the internals of the compiler remained the same, which allow indirect passes of tuples, like in the examples from the question.
来源:https://stackoverflow.com/questions/54283053/implicit-cast-function-receiving-tuple