Какие рекурсивные структуры данных можно реализовать с помощью indirect enum в Swift?

«Какие рекурсивные структуры данных можно реализовать с помощью indirect enum в Swift?» — вопрос из категории Алгоритмы и структуры данных, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово indirect позволяет enum хранить экземпляр своего же типа в качестве ассоциированного значения, что делает его идеальным для реализации рекурсивных структур данных.

Примеры реализаций:

  1. Связный список (Linked List):

    indirect enum LinkedList<Element> {
        case empty
        case node(Element, LinkedList<Element>) // Рекурсия: узел указывает на следующий узел (или empty)
    }
    
    // Использование:
    let list: LinkedList<Int> = .node(1, .node(2, .node(3, .empty)))
  2. Бинарное дерево (Binary Tree):

    indirect enum BinaryTree<Element> {
        case empty
        case node(Element, BinaryTree<Element>, BinaryTree<Element>) // Левый и правый потомки
    }
    
    // Пример дерева:
    let tree: BinaryTree<Int> = .node(10,
                                      .node(5, .empty, .empty),
                                      .node(20, .empty, .empty))
  3. Абстрактное синтаксическое дерево (AST) или выражение:

    indirect enum ArithmeticExpression {
        case number(Double)
        case addition(ArithmeticExpression, ArithmeticExpression)
        case multiplication(ArithmeticExpression, ArithmeticExpression)
    }
    
    // Выражение: (5 + 2) * 3
    let expr: ArithmeticExpression = .multiplication(
                                        .addition(.number(5), .number(2)),
                                        .number(3)
                                     )

Почему indirect? Без него компилятор Swift не может определить фиксированный размер enum, так как он потенциально бесконечен. indirect указывает, что связанное значение хранится по ссылке (в куче), решая эту проблему.