これは?
みなさんはSwiftの 再帰的列挙型 というものをご存知でしょうか。
本稿では、意外と知られていない 再帰的列挙型 の使い方について説明します。
再帰的列挙型とは?
再帰的列挙型とは、 associated value としてその列挙型自身を再帰的に持つ列挙型のことです。
言葉だけではわかりにくいので、実際に例を示します。
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
上記のプログラムは、単純な演算を行うための再帰的列挙型の定義です。
一つ目のケースはInt型を associated value として持ちます。
演算のために使う被演算子の定義です。
二つ目と三つ目のケースはそれぞれ加算と乗算の定義です。
そしてどちらも ArithmeticExpression
自身を associated value として持ちます。
このような場合、caseの前に indirect修飾子 を付加します。
活用例
例えば、この ArithmeticExpression
を利用して、 (5 + 4) * 2
という演算を処理してみましょう。
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let two = ArithmeticExpression.number(2)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, two)
上記のプログラムは以下のような定義となります。
-
ArithmeticExpression
のnumber
としてfive
を初期化 -
ArithmeticExpression
のnumber
としてfour
を初期化 -
ArithmeticExpression
のnumber
としてtwo
を初期化 -
ArithmeticExpression
のaddition
としてfive
とfour
を被演算子に指定してsum
を初期化 -
ArithmeticExpression
のmultiplication
としてsum
とtwo
を被演算子に指定してproduct
を初期化
さて、これで演算を行う準備が整いました。
変数 product
は (5 + 4) * 2
の演算を ArithmeticExpression
として持つことになります。
あとはこの ArithmeticExpression
を引数に取る評価関数を定義します。
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value):
return value
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right):
return evaluate(left) * evaluate(right)
}
}
print(evaluate(product))
// Prints "18"
上記の evaluate
関数は以下のような定義となります。
- ArithmeticExpressionを引数として受け取る
- switch文でケースを分岐する
- .numberならば: その associated value であるInt型を返す
- .additionならば: 2つの被演算子をそれぞれ
evaluate
関数に引数として渡してその結果を加算する - .multiplicationならば: 2つの被演算子をそれぞれ
evaluate
関数に引数として渡してその結果を乗算する
この関数 evaluate
に product
を引数として渡すと、その演算結果である 18
が返ってきます。
このように、再帰的列挙型は再帰関数とともに扱うことで非常に直感的なコーディングが可能になります。