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