🔥 재귀 열거형

349자
4분

열거형(enumeration)은 관련된 값들을 하나의 그룹으로 묶어서 표현하는 타입입니다. 그런데 가끔은 열거형의 case가 열거형 자신의 인스턴스를 연관값(associated value)으로 가지는 경우가 있어요. 이런 열거형을 재귀 열거형(recursive enumeration)이라고 부릅니다.

재귀 열거형을 정의할 때는 컴파일러에게 간접 계층(layer of indirection)을 삽입하도록 지시하기 위해 indirect 키워드를 case 앞에 써줘야 해요. 예를 들어, 간단한 산술 표현식을 저장하는 열거형을 아래와 같이 정의할 수 있겠죠.

enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
swift

위 코드에서 additionmultiplication case는 연관값으로 ArithmeticExpression 타입을 가지고 있어요. 즉, 산술 표현식이 다른 산술 표현식을 포함할 수 있다는 뜻이죠.

만약 열거형의 모든 case가 연관값을 가진다면 indirect 키워드를 열거형 시작 부분에 한 번만 써주면 됩니다.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}
swift

이렇게 정의한 ArithmeticExpression 열거형은 세 종류의 산술 표현식을 저장할 수 있어요.

  1. 하나의 정수(number)
  2. 두 개의 표현식을 더한 것(addition)
  3. 두 개의 표현식을 곱한 것(multiplication)

예를 들어 (5 + 4) * 2 라는 표현식을 나타내 보겠습니다. 곱셈의 오른쪽에는 숫자가, 왼쪽에는 덧셈 표현식이 있네요. 이렇게 데이터가 중첩되어 있으므로 이를 저장하는 열거형도 중첩, 즉 재귀적이어야 합니다.

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
swift

재귀적인 구조의 데이터를 다루기에 적합한 방법 중 하나는 재귀 함수를 사용하는 거예요. 아래는 위에서 정의한 산술 표현식을 계산하는 함수를 재귀적으로 구현한 예시입니다.

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))
// "18" 출력
swift

위 함수는 다음과 같이 동작해요.

  • .number case일 때는 연관값을 그대로 반환합니다.
  • .addition case일 때는 왼쪽 표현식과 오른쪽 표현식을 각각 재귀적으로 계산한 뒤 그 결과를 더합니다.
  • .multiplication case일 때는 왼쪽 표현식과 오른쪽 표현식을 각각 재귀적으로 계산한 뒤 그 결과를 곱합니다.

이렇게 열거형의 case가 자기 자신을 연관값으로 가질 수 있게 하면 계층적이고 재귀적인 데이터 구조를 표현하기에 아주 유용하답니다. 🌳

           product
             / \\
            /   \\
           /     \\
          /       \\
         /         \\
       sum         number
       / \\           |
      /   \\          2
     /     \\
 number   number
    |       |
    5       4
text