Swift参数包如何解决元组比较的重复性实现问题?
Swift参数包如何解决元组比较的冗余问题?
Swift进化提案的动机部分提到,实现元组比较时会出现大量冗余代码——必须为不同长度的元组重复编写<运算符的实现,还受限于预先设定的最大元组长度(比如六元组):
func < (lhs: (), rhs: ()) -> Bool func < <A, B>(lhs: (A, B), rhs: (A, B)) -> Bool where A: Comparable, B: Comparable func < <A, B, C>(lhs: (A, B, C), rhs: (A, B, C)) -> Bool where A: Comparable, B: Comparable, C: Comparable
核心疑问
查看Swift 6头文件会发现,元组的<运算符声明并未改变,也没有使用参数包;而且参数包看起来是针对可变参数设计的,而非元组。我自己实现了可变参数列表的比较函数:
func isLessThan<each T: Comparable>(lhs: repeat each T, rhs: repeat each T) -> Bool { for pair in repeat (each lhs, each rhs) { if pair.0 >= pair.1 { return false } } return true }
调用方式是:
let result = isLessThan(lhs: 1, "a", rhs: 2, "b")
但这是可变参数列表而非元组,核心问题是无法直接将元组(或序列)转为可变参数列表。那参数包到底怎么解决最初的元组比较冗余问题?
答案:参数包支持元组的解构与打包
参数包的设计初衷就是解决这类“同质结构长度可变导致的代码重复”问题,元组正是典型的适用场景——参数包可以直接与任意长度的元组进行双向转换,只是目前Swift标准库还未完成这部分的更新(可能出于兼容性或演进节奏的考虑)。
用参数包实现通用元组比较的思路如下:
// 利用参数包定义通用的元组比较逻辑 func compare<each T: Comparable>(lhs: (repeat each T), rhs: (repeat each T)) -> Bool { for (left, right) in repeat (each lhs, each rhs) { if left < right { return true } else if left > right { return false } // 相等则继续比较下一个元素 } // 所有元素都相等,返回false return false } // 为任意长度的可比较元组扩展<运算符 extension Comparable where Self: Tuple { static func < (lhs: Self, rhs: Self) -> Bool { return compare(lhs: lhs, rhs: rhs) } }
这里的关键是:
- 参数包的
repeat each T可以直接匹配任意长度的元组类型,编译器会自动将元组解构为参数包的元素集合; - 反过来,也可以将参数包元素打包成元组返回,实现双向转换;
- 只需要编写一次比较逻辑,就能覆盖所有长度的可比较元组,彻底消除冗余代码。
之所以标准库还没更新,是因为Swift的演进需要兼顾现有代码的兼容性,新特性的落地通常会分阶段推进,但参数包从设计上已经完美解决了元组比较的冗余问题。
内容的提问来源于stack exchange,提问作者matt
相关产品推荐
相关产品推荐

