Adding toggle to Bool
01 何が問題だったのか
Bool の値を反転させたい場面はよくありますが、それまでの Swift には反転を直接表現するメソッドがなく、自分自身に否定演算子 ! を適用した値を代入し直す書き方をするしかありませんでした。
isEnabled = !isEnabled
変数名が短ければさほど気になりませんが、ネストした構造体のプロパティなど対象が長いパス式になると、同じ式を左辺と右辺の両方に書く必要があり、重複と視認性の悪さが目立ちます。
myVar.prop1.prop2.enabled = !myVar.prop1.prop2.enabled
この書き方は単に冗長なだけでなく、同じ名前の Bool プロパティが複数あるときに、左辺と右辺で違うものを指すように書き間違えるといったミスを招きやすいという問題もありました。
02 どのように解決されるのか
Bool に、自分自身を反転させる mutating メソッド toggle() を追加します。意味は someBool = !someBool と同じで、呼び出すと true と false が入れ替わります。
extension Bool {
mutating func toggle() {
self = !self
}
}
これによって、長いパス式に対しても重複なく反転を書けるようになります。
var isEnabled = false
isEnabled.toggle()
// isEnabled == true
myVar.prop1.prop2.enabled.toggle()
メソッド呼び出しなので左辺と右辺で同じ式を繰り返す必要がなく、取り違えによるミスも起きません。
名前については invert・negate・flip といった候補も検討されましたが、議論の中で toggle が最も自然に意図を表すとして採用されました。標準ライブラリ内の対応関係としても、前置の - 演算子に対して negate() メソッドがあるのと同様に、前置の ! 演算子に対する mutating なメソッドとして toggle() が位置付けられます。
なお、同じ意味を持つ非破壊的な(自身は変更せずに反転した値を返す)バリエーションについても議論されましたが、それは本提案のスコープ外とされ、! 演算子で十分であるという判断からこの提案には含まれていません。