Indirect enums - Swift 3.0

Enums are one of my favorite parts in any language. With Swift they've got extra functionality such as adding functions, associated values and Indirect Enums.

So what are indirect enums? I have learned enums in other language, but never came across any language which offers similar functionality. At least not that I am aware of. Let's see how they function. Indirect enums are kind of recursive enums which encapsulates its own type.

Developers can indicate the recursive enums by writing indirect before enum case which tells the compiler to insert the necessary level of indirection.

Indirect keyword can also be written before the enum keyword as opposed to individual cases. This enables indirection for all enum cases

Let's look at the example taken directly from Official Apple documentation on enums


enum ArithmeticExpression {
    case value(Int)
    indirect case Addition(ArithmeticExpression, ArithmeticExpression)
    indirect case Multiplication(ArithmeticExpression, ArithmeticExpression)
}

// We can initialize custom values with ArithmeticExpression enums as follows

let firstNumber = ArithmeticExpression.value(10)
let secondNumber = ArithmeticExpression.value(2)
let addition = ArithmeticExpression.Addition(firstNumber, secondNumber)

let multiplication = ArithmeticExpression.Multiplication(firstNumber, secondNumber)

This is fine, but how do we evaluate this recursive expression? Looks like we need recursive function to work with recursive enums. Let's write one as follows.


func computeValue(input: ArithmeticExpression) -> Int {
    switch input {
    case .value(let val):
        return val
    case .Addition(let exp1, let exp2):
        return computeValue(input: exp1) + computeValue(input: exp2)
    case .Multiplication(let exp1, let exp2):
        return computeValue(input: exp1) * computeValue(input: exp2)
    }
}

// Now utilizing this function we can easily compute the values of expressions above,

// additionResult = 12
let additionResult = computeValue(input: addition)

// multiplicationResult = 20
let multiplicationResult = computeValue(input: multiplication)

Using the same principle you can add other custom operators and complex expressions. However, as far as I see indirect enums are best suited to deal with recursive computation. You can utilize simpler constructs for non-recursive operations.

Other use-case I can think of is binary tree. In this case you can maintain a enum which holds two cases. Either tree is empty or it has value and left and right children as further subtrees. This can be summarized as follows


enum BinaryTree<T> {
    case empty
    indirect case node(BinaryTree, T, BinaryTree)
}

// In the similar fashion individual nodes can be formed as follows
let node1 = BinaryTree.node(.empty, "5", .empty)
let node2 = BinaryTree.node(.empty, "500", .empty)
let node3 = BinaryTree.node(.empty, "50", .empty)

let node4 = BinaryTree.node(node1, "+", node2)
let node5 = BinaryTree.node(node4, "*", node3)

At the end, it becomes quite easy to visualize binary tree based on this data

This article should provide you with basic understanding of indirect enums. This is pretty powerful concept and if used wisely, could provide immense benefit. If you have further questions, you can refer to Apple documentation linked below and as always you can also Tweet or message me. I will be more than happy to help with any doubts you may have

Reference:

Apple developer portal

raywenderlich.com