次は SE-0015: タプル比較演算子 です。だいぶ意訳です。
原文に従ってこの訳は Apache License 2.0 とします。
タプル比較演算子
- 提案: SE-0015
- 著者: Kevin Ballard
- ステータス: Swift 2.2 で実装された (Pull request)
- レビューマネージャ: Dave Abrahams
はじめに
あるアリティ(訳注:タプルの要素数)以下のタプルの比較演算子を実装します。
動機
比較可能な値のタプルを比較しようとして、タプルは比較演算子を何もサポートしていないことに気づくとイラッとするものです。比較可能な値のタプルの ==
と !=
の定義は極めて明らかです。また(辞書順の)順序比較演算子の定義もほぼ明らかです。
タプルの比較にとどまらず、タプルを比較可能にするとタプルに似た構造体の比較演算子を実装するのも容易になります。適切な演算子が構造体のプロパティを含むタプルも単純に比較できるからです。
提案手法
Swift の標準ライブラリはあるアリティ以下の全てのタプルに対する比較演算子の汎用的な実装を提供するべきです。そのアリティは利便性(全てのタプルでサポート)とコードサイズ(どの定義も標準ライブラリのコードサイズを増やす)とのバランスによって選ばれるべきです。
Swift が条件付きプロトコル準拠とタプルの拡張もサポートするようになった場合は、バランスを加味して選んだアリティ以下のすべてのタプルも Equatable
と Comparable
に準拠するよう条件付きで宣言されるべきです。
Swift が可変長型パラメータを採用するようになった場合は、演算子(プロトコル準拠についても)の再定義について検討するべきです。コードサイズが膨れ上がるのを防げるかもしれません。
詳細設計
実際の定義は gyb で生成するでしょう。ここで提案するアリティは 6 です。これは大幅はコードサイズの増加なしにほとんどの適切な使い方をしているタプルをサポートするのに十分な長さです(私の好みほどは長くありませんが)。アリティ 6 でこの提案を実装してみたところ、Ninja-ReleaseAssert ビルドの libswiftCore.dylib
(macosx 用と iphoneos 用の両方) のコードサイズの増加は 43.6KiB でした。これは 1.4% の増加です。
自動生成された定義は以下のようになります(アリティ 3 の場合):
@warn_unused_result
public func == <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
return lhs.0 == rhs.0 && lhs.1 == rhs.1 && lhs.2 == rhs.2
}
@warn_unused_result
public func != <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
return lhs.0 != rhs.0 || lhs.1 != rhs.1 || lhs.2 != rhs.2
}
@warn_unused_result
public func < <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
if lhs.0 != rhs.0 { return lhs.0 < rhs.0 }
if lhs.1 != rhs.1 { return lhs.1 < rhs.1 }
return lhs.2 < rhs.2
}
@warn_unused_result
public func <= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
if lhs.0 != rhs.0 { return lhs.0 < rhs.0 }
if lhs.1 != rhs.1 { return lhs.1 < rhs.1 }
return lhs.2 <= rhs.2
}
@warn_unused_result
public func > <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
if lhs.0 != rhs.0 { return lhs.0 > rhs.0 }
if lhs.1 != rhs.1 { return lhs.1 > rhs.1 }
return lhs.2 > rhs.2
}
@warn_unused_result
public func >= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool {
if lhs.0 != rhs.0 { return lhs.0 > rhs.0 }
if lhs.1 != rhs.1 { return lhs.1 > rhs.1 }
return lhs.2 >= rhs.2
}
既存のコードに対する提供
既存のコードに影響はないはずです。
考えられる代替案
アリティ 12 までのタプルをサポートするよう Ninja-ReleaseAssert ビルドで試してみましたが、コードサイズの増加は 171Kib (5.5%の増加)でした。他のアリティについては試していません。