区分元组和多元函数

时间:2018-02-14 18:06:33

标签: swift

我在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))

enter image description here 但是如果我从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}}在自动完成代码中。

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知道正确的类型;游乐场只是显示错误的东西。