Swift 中元组的奇怪展开

Weird unwraping of tuples in Swift

在下图中,您可以看到在 playground 中执行的代码感觉不对。但是 Swift 编译器完全没问题。由于某种原因,元组的嵌入深度减少到一个。

要更有表现力:

有人知道这是错误还是功能?

(Int, Int) 是元组类型(其中括号是其类型的一部分),就像 ((Int, Int)) 是相同的元组类型,但包裹在一对额外的(冗余)括号中,正如 (((Int, Int))) 与前两个元组类型相同,但包含在两组(冗余)括号中。

var a: (((Int, Int)))
print(type(of: a)) // (Int, Int)

仅当您开始在嵌套级别上组合不同类型时,其他括号才会生效,例如

var a: ((Int, Int), Int)
print(type(of: a)) // ((Int, Int), Int)`.

现在,为什么第一个地图关闭失败,而第二个没有?

当使用尾随闭包时,您可以

  1. 使用shorthand参数名称([=16=], ...),或
  2. 使用显式命名(或显式省略名称,“_”)参数。

您的两个示例都尝试使用命名参数,但只有第二个示例遵循使用名称参数的规则:即必须提供参数名称(提供参数 types闭包 return 类型是可选的,但在某些情况下由于编译器类型推断限制而需要)。

研究以下示例:

/* all good */
arr.map { (a) in
    2*a /* ^-- explicitly name parameter */
}

// or
arr.map { a in
    2*a /* ^-- explicitly name parameter */
}

/* additional parantheses: 
       error: unnamed parameters must be written with the empty name '_'

   the closure now believes we want to supply parameter name as well as 
   an explicit type annotation for this parameter */
arr.map { ((a)) in
    2*a /*  ^-- compiler believes this is now a _type_, and prior to realizing 
                that it is not, prompts us for the error that we have not 
                supplied a parameter name/explicly omitted one with '_' */
}

/* additional parantheses: 
       error: use of undeclared type 'a' */
arr.map { (_: (a)) in
    1   /* ^-- type omitted: compiler now realize that 'a' is not a type */
}

/* fixed: all good again! */
arr.map { (_: (Int)) in
    1
}

在您的第一个示例中,您 将您的元组包装在 paranthesis 中尝试命名的元组元素(在闭包的 .... in 部分中)(正如显示的错误上面),这意味着 Swift 认为它是一个 类型 (类型 (x, y)),在这种情况下,编译器需要包含一个内部参数名称或显式省略一个(使用 _)。只有当您提供参数名称时,编译器才会意识到 xy 不是有效类型。

在您的第二个示例中,您只是直接将两个元组成员的闭包绑定到内部参数名称 xy,选择不显式键入注释这些参数(没关系)。