Posted at

【Swift】使いこなせば便利?〜再帰的列挙型〜

More than 1 year has passed since last update.


これは?

みなさんは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)

上記のプログラムは以下のような定義となります。



  • ArithmeticExpressionnumber として five を初期化


  • ArithmeticExpressionnumber として four を初期化


  • ArithmeticExpressionnumber として two を初期化


  • ArithmeticExpressionaddition として fivefour を被演算子に指定して sum を初期化


  • ArithmeticExpressionmultiplication として sumtwo を被演算子に指定して 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 関数は以下のような定義となります。


  1. ArithmeticExpressionを引数として受け取る

  2. switch文でケースを分岐する


    • .numberならば: その associated value であるInt型を返す

    • .additionならば: 2つの被演算子をそれぞれ evaluate 関数に引数として渡してその結果を加算する

    • .multiplicationならば: 2つの被演算子をそれぞれ evaluate 関数に引数として渡してその結果を乗算する



この関数 evaluateproduct を引数として渡すと、その演算結果である 18 が返ってきます。

このように、再帰的列挙型は再帰関数とともに扱うことで非常に直感的なコーディングが可能になります。


参考

Apple Inc. “The Swift Programming Language" -Enumerations