Recursive Enums

Introduction

Welcome to Lesson 5 of Advanced Enum. In this lesson, you will discover how to create a complex enum structure using a recursive. Some may have not heard the term, "recursive" before. I will briefly show you what a recursive function is. Nonetheless, this lesson may be challenging.

Problem

Enum contains its own enum type

Recursive Function

Let us begin this lesson by learning about what a recursive function is.

func recursiveFunction() {
  print("Hi!")
  recursiveFunction() // loop
}

When you execute the recursiveFunction, it never ends.

recursiveFunction()
// "Hi'"
// "Hi'"
// ...
// "Hi"

Design Enum

Create an enum, ArithmeticExpression. It contains three cases with associated types. Two of the cases contain its own enum type, ArithmeticExpression. The indirect keyword is needed to indicate that the enum is a special animal.

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

You may initialize using the number case or with addition or multiplication.

ArithmeticExpressions.number(4)
ArithmeticExpressions.addition(.number(4), .number(4))

let five = ArithmeticExpressions.number(5)
let four = ArithmeticExpressions.number(4)

You may create a recursive function to execute, addition and multiplication.

func evaluate(_ expression: ArithmeticExpressions) -> 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)
  }
}

Important: You may have to look at the function multiple times until you get it. Don't give up.

Let us execute the function.

evaluate(ArithmeticExpressions.number(4))
evaluate(ArithmeticExpressions.addition(.number(4), .number(4))) // 8
let multiplicationEnumType = ArithmeticExpressions.multiplication(.number(4), .number(4))
evaluate(multiplicationEnumType)  // 16

Alternative Normal Enum

A recursive enum to do addition and multiplication is an overkill. Let us use a normal one.

enum Operation {
  case addition(Int, Int)
  case multiplication(Int, Int)

  var result: Int {
    switch self {
    case let .addition(number1, number2):
      return number1 + number2
    case let .multiplication(number1, number2):
      return number1 * number2
    }
  }
}

Execute.

Operation.addition(4, 4).result

However, I personally don't like the you have to use result to get the final value.

Another Alternative

You may create a struct along with functions.

struct StructOperation {
  func addTwoNumbers(_ number1: Int, _ number2: Int) -> Int {
    return number1 + number2
  }
  func multiplfyNumbers(number1: Int, number2: Int) -> Int {
    return number1 * number2
  }
}

Execute

StructOperation().addTwoNumbers(4, 9)

This feels better. Yet, let us make it more zen.

My Choice

Use closures instead.

struct MathOperation {
  static let addition: (Int, Int) -> Int = { $0 + $1 }
  static let multiplication: (Int, Int) -> Int  = { $0 * $1 }
}

Execute

MathOperation.addition(10, 10) // 20

The best.

Source Code

7005_recursive_enum.playground

References

The Swift Programming Language (Swift 3.1)

Conclusion

One of the code smells is "needless complexity". You don't need to be fancy. Remember, protocols and enums are double edged swords. If you don't know how handle them well, it may hurt or even kill you. In Chapter 8, you will learn in-detail about how an indirect enum works using a binary tree data structure.

In the following lesson, you will learn how to combine enums with generics.

Note: Learn Swift with Bob is available on Udemy. If you wish to receive a discount link, you may sign up here.

results matching ""

    No results matching ""