我在playground中编写了这个函数,它具有元组类型的 value 参数,返回类型是元组。
func tuple(value: (Int, Int) ) -> (first: Int, second: Int) {
let firstGrabTuple = value.0 + 5
let secondGrabTuple = value.1 + 5
return (firstGrabTuple, secondGrabTuple)
}
然后我将它分配给常量调用closure
let closure = tuple
//(Playground showing) let closure became a function of type (Int, Int) -> (first: Int, second: Int)
然后进行双重检查,我编写了另一个以闭包为参数的函数,类型为((Int, Int)) -> (Int, Int)
func anotherTuple(_ closure: ((Int, Int)) -> (Int, Int)) {
closure((5, 5))
}
当我致电anotherTuple
anotherTuple { (x) -> (Int, Int) in
let first = x.0 + 5
let second = x.1 + 5
return (first, second)
}
//prints .0 10, .1 10 as expected
所以我的问题如上所述当我将第一个函数tuple
分配给名为closure
的常量变为类型(Int, Int) -> (first: Int, second: Int)
时。但在第二个函数中如果我必须使用类型的参数作为元组,我必须将其参数设置为双括号,如(_ closure: ((Int, Int)) -> (Int, Int))
。
但是如果我从anotherTuple
函数参数中删除那些双括号,那么它只会期望2个值作为多参数函数。没有错误用作多参数函数而不是元组参数为什么是这样?添加图像以获取更多细节。
第二个问题是为什么
let closure = tuple
//let closure became a function of type (Int, Int) -> (first: Int, second: Int)
未成为((Int, Int)) -> (first: Int, second: Int)
**注意 - 当我尝试将名为closure
的常量作为参数传递给另一个函数时,该函数将关闭((Int, Int)) -> (Int, Int)
类型,然后在键入closure
时将其显示为{{ 1}}在自动完成代码中。
答案 0 :(得分:2)
你纠正了混乱。我有点只是重述你的理解,然后说'#34;是的,Swift中的元组很奇怪而且有点破碎。"
Swift没有区分以某种方式采用元组与多个参数的函数,但确实以其他方式区分。 (这是在斯威夫特的生活中避免元组的众多原因之一。)
首先,这两个函数在Swift中几乎相同类型(注意Void
和()
是相同的):
func tuple(value: (Int, Int) ) {} // (Int, Int) -> Void
func two(value1: Int, value2: Int) {} // (Int, Int) -> Void
他们看起来一样。但是,如果您定义一个接受该类型的函数,它就不能tuple
:
func take(f: (Int, Int) -> Void) {}
take(f: tuple) // Fails
take(f: two) // ok
但是如果定义一个取((Int, Int)) -> Void
的函数,它可以接受任何一个函数:
func take(f: ((Int, Int)) -> Void) {}
take(f: tuple) // ok
take(f: two) // ok
这表明(Int, Int) -> Void
是((Int, Int)) -> Void
的子类型。
但变数相信这一点:
var f: (Int, Int) -> Void
f = tuple // Ok
f = two // Ok
var g: ((Int, Int)) -> Void
g = tuple // ok
g = two // ok
g = f // ok
f = g // ok
这表明(Int, Int) -> Void
和((Int, Int)) -> Void
属于同一类型。但take
功能表明他们不是。
是。所有这一切都是同时存在的。接受元组的函数在Swift中不是一个连贯的类型(它们不占用类型层次结构中明确划分的点)。这就是我们今天在Swift的所在地。
旧的,不正确的答案。
<击> 这只是游乐场的一个怪癖,您可以随意打开radar。
如果您选中 type(of: closure)
,它会打印您期望的类型。 Swift知道正确的类型;游乐场只是显示错误的东西。