LoginSignup
3
3

More than 5 years have passed since last update.

SwiftのAssociated Values(enum)とパターンマッチで無理やりSet

Last updated at Posted at 2014-08-25

enumのAssociated Valuesの使い方を練習してみました.こういう使い方もできるな,という程度の遊びです.

enum Option {
    enum Kind {
        case None, Opt0, Opt1, Opt2, Opt3
    }

    case _Set(Kind, Kind, Kind, Kind)

    static func Set(opt: Option.Kind, _ opts: Option.Kind...) -> Option {
        switch opts.count {
        case 0:  return ._Set(opt, .None,   .None,   .None)
        case 1:  return ._Set(opt, opts[0], .None,   .None)
        case 2:  return ._Set(opt, opts[0], opts[1], .None)
        case 3:  return ._Set(opt, opts[0], opts[1], opts[2])
        default: return ._Set(.None, .None, .None, .None) // error
        }
    }

    func has(o: Option.Kind) -> Bool {
        switch self {
        case ._Set(o, _, _, _): return true
        case ._Set(_, o, _, _): return true
        case ._Set(_, _, o, _): return true
        case ._Set(_, _, _, o): return true
        default: return false
        }
    }

    func has(o: Option) -> Bool {
        switch o {
        case ._Set(let a, let b, let c, let d):
            return has(a) && has(b) && has(c) && has(d)
        default: return false
        }
    }
}

要素チェック用のhasとサブセットチェック用のhasを定義.

  • 要素用のは,ドントケア(wildcard pattern)の_をたっぷり使ってタプル内を全検査.タプル内の何処かに要素があればtrueを返す.

  • サブセット用のは,タプルパターン&バリューバインディングパターンで全要素を分解し,それそれを要素用のhasでチェックしています.

Kindが増えると機械的とは言え,実装するの面倒くさいですね.

使い方,

var x = Option.Set(.Opt0, .Opt1)
var y = Option.Set(.Opt1, .Opt2)
var z = Option.Set(.Opt2, .Opt3)

x.has(.Opt1)    // true
y.has(.Opt0)    // false
z.has(.Opt3)    // true

x.has(y)        // false
y.has(z)        // false
z.has(x)        // flase

x.has(Option.Set(.Opt0, .Opt1))    // true
x.has(Option.Set(.Opt0, .Opt3))    // false

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3