元组比较如何工作

时间:2019-02-25 18:45:28

标签: swift tuples

let p1 = (name: "John", age:12)
let p2 = (color: "Red", size:12)


if p1 == p2 {
    print("equal")
}else {
    print("not equal")
}

由于不同的参数名称和代码无法编译,我期望这两个元组不兼容。但这很好。好奇地知道如何。

Swift是否根据属性类型自动创建==运算符,然后只进行简单的lhsrhs。是吗?

编辑:

func givePerson() -> (name: String, age: Int)? {
    return ("alex", 2)
}

func extract() {
    var p3 : (Name: String, age: Int)

    if let person = giveName() as? (Name: String, age: Int) {
        p3 = person
        print(p3)
    }else {
        print("p3 not defined")
    }

}

extract() // p3 not defined

我的extract函数失败,只是因为我得到的Arity名称不正确。这也是预期的吗?与元组比较有什么不同?

2 个答案:

答案 0 :(得分:4)

标准库defines tuple comparison operators,用于2个元素元组,最多6个元素元组。它是通过使用元编程工具GYB(“生成样板”)来完成的,该工具允许嵌入式Python代码从模板生成文件。

生成的元组比较运算符最终看起来像:

public func == <A, B>(lhs: (A, B), rhs: (A, B)) -> Bool

public func == <A, B, C>(lhs: (A, B, C), rhs: (A, B, C)) -> Bool

public func == <A, B, C, D>(lhs: (A, B, C, D), rhs: (A, B, C, D)) -> Bool

// ...

使用您的代码:

let p1 = (name: "John", age: 12)
let p2 = (color: "Red", size: 12)

if p1 == p2 {
    print("equal")
} else {
    print("not equal")
} 

编译器将调用两个元素的元组比较运算符。您会注意到,没有定义的元组比较运算符将元组标签用作其参数。
(name: String, age: Int)(color: String, size: Int)都可以传递给(A, B)的原因是,编译器实现了一个隐式转换,该转换可以剥离其标签的元组。因此,这两个参数的标签都被剥夺,并且都以(String, Int)的形式传递。

这就是使以下法律合法的原因:

let p1 = (name: "John", age: 12)
let p2: (String, Int) = p1 // Legal.

编译器还具有一个隐式转换,该转换可以添加任意元组到元组,这使事情变得奇怪:

let p1 = ("John", 12)
let p2: (foo: String, bar: Int) = p1 // Legal.

但是,禁止直接重命名标签:

// Indirect renaming ✅
let p1 = (name: "John", age: 12)
let p2: (String, Int) = p1
let p3: (foo: String, bar: Int) = p2

// Put together ✅
let p4: (foo: String, bar: Int) = p1 as (String, Int)

// Direct renaming ❌
let p4 = (name: "John", age: 12)
let p5: (foo: String, bar: Int) = p4

这就是您在as?强制转换中看到的行为。像上面的例子一样,首先强制使用未标记的形式:

func givePerson() -> (name: String, age: Int)? {
  return ("alex", 2)
}

func extract() {
  var p3: (Name: String, age: Int)
  if let person = givePerson() as (String, Int)? as? (Name: String, age: Int) {
    p3 = person
    print(p3)
  } else {
    print("p3 not defined")
  }

}

extract() // (Name: "alex", age: 2)

答案 1 :(得分:2)

为Tuples定义了==运算符(对于2至7的元组),但是由于元组不符合协议,因此它们不是Equatable

标准库仅定义6个独立的==运算符,每个运算符采用两个元组Arity 2、3,...,7。