SwiftでもRubyの"!!"演算子を再現したい

  • 7
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Swiftを触っていると、Rubyではお馴染みの!!演算子を使いたくなることが度々あるので即興で作ってみました。

簡単に!!演算子の説明をすると、オブジェクトがnilかどうかをBoolで返してくれるようになるため、if構文などでobject != nilの代わりに!!objectと記述できるようになります。
SwiftではObjective-Cと違い、分岐条件は論理値であることが求められるため、素直にnilを条件としたい場合などに有用かと思います。

prefix operator !! {}
prefix func !!<T> (object: T?) -> Bool {
    if let bool = object as? Bool {
        return bool
    }
    return object != nil
}

結果

!!NSObject() // => true
!!true       // => true
!!false      // => false

var str1: String?
!!str1       // => false
str1 = "foo"
!!str1       // => true

この結果をさらに反転させるには!(!!NSObject())のような書き方をしますが、気持ち悪いので!!!演算子も定義します。

prefix operator !!! {}
prefix func !!!<T> (object: T?) -> Bool {
    return !(!!object)
}

// 結果
!!!NSObject() // => false
!!!true       // => false
!!!false      // => true

var str2: String?
!!!str2       // => true
str2 = "foo"
!!!str2       // => false

ただ反転させてるだけです。

使用例

var array: [AnyObject]?
array?.isEmpty   // => nil
!!array?.isEmpty // => false

if !!array?.isEmpty {
    // arrayがnilか空の場合
}

// 同上
if array == nil || array!.isEmpty {
    // arrayがnilか空の場合
}

上記の例ではarraynilとなっているため、2行目は通常のオプショナルチェーンなのでnilを返します。
一方、!!演算子をつけた場合はnilの代わりにfalseが返されるため、このままif文で使用できます。

テストはしていないので何かあればコメント歓迎です。

2014.11.17 追記

  • プリミティブ型に対応するため引数をAnyObject?からAny?に変更

2015.1.5 追記

  • 引数をジェネリックス化
  • 使用例を追加