Recursive Enums
A recursive enum is one that can contain another copy of itself inside it, like a set of nested boxes each holding a smaller box.
In this page:
Syntax
indirect enum EnumName {
case leaf(Type)
case node(EnumName, EnumName) // holds itself
}
func process(_ e: EnumName) -> Type {
switch e {
case .leaf(let v): return v
case .node(let l, let r): return process(l) /* combine */ process(r)
}
}
Declaring a Recursive Enum
Marking a case indirect allows it to hold another instance of the same enum, enabling recursive, tree-like structures.
Example: Declaring a Recursive Enum
indirect enum ArithmeticExpression {
// Case `number`
case number(Int)
// Enum case(s): `addition(ArithmeticExpression, ArithmeticExpression)`
case addition(ArithmeticExpression, ArithmeticExpression)
}
// Declare a constant `expression`, set to `ArithmeticExpression.addition(.number(3), .number(4))`
let expression = ArithmeticExpression.addition(.number(3), .number(4))
// Print `expression` to the console
print(expression)
Login to try C/C++/Java/PHP code in the editor
Evaluating a Recursive Enum
A recursive function that mirrors the enum's structure can walk through nested cases, evaluating them down to a final result.
Example: Evaluating a Recursive Enum
indirect enum ArithmeticExpression {
// Case `number`
case number(Int)
// Enum case(s): `addition(ArithmeticExpression, ArithmeticExpression)`
case addition(ArithmeticExpression, ArithmeticExpression)
}
// Define the function `evaluate` taking `expression` and returning an Int
func evaluate(_ expression: ArithmeticExpression) -> Int {
// Switch on `expression` and branch by case
switch expression {
// Case: `.number(let value)`
case .number(let value):
// Return `value` from this function
return value
// Case: `.addition(let left, let right)`
case .addition(let left, let right):
// Return `evaluate(left) + evaluate(right)` from this function
return evaluate(left) + evaluate(right)
}
}
// Declare a constant `expression`, set to `ArithmeticExpression.addition(.number(3), .addition(.number(4), .number(5)))`
let expression = ArithmeticExpression.addition(.number(3), .addition(.number(4), .number(5)))
// Print `evaluate(expression)` to the console
print(evaluate(expression))
Login to try C/C++/Java/PHP code in the editor
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the
view already swaps in the hi_ translation fields (or blanks these
out if untranslated), so this renders correctly for both languages
without a lang_code check here. #}
Common Mistakes
- Forgetting the
indirectkeyword on a case (or the whole enum) that refers back to itself; without it, Swift can't compute a fixed size for the type. - Confusing
indirect case(marks one case as needing indirection) withindirect enum(marks the whole enum), both are valid depending on need. - Writing a recursive function over a recursive enum without a proper base case, causing infinite recursion.
Chapter Summary
- A case that contains the enum's own type as an associated value must be marked
indirect. indirecttells Swift to store that case's data via a pointer instead of inline.- Recursive enums are perfect for modeling nested structures like arithmetic expressions or linked lists.
- Functions processing a recursive enum typically use recursion themselves, matching each case.
🔒
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: