Swift: Putting Your Generics in a Box

One of my favorite functional patterns that I now use in Swift is the Result enum  for error handling:

enum Result<T> {
    case Success(T)
    case Failure(NSError)
}

I won’t go into much detail on this, but I highly recommend reading Alexandros Salazar’s great explanation of why this is magic. Also make sure to check out Scott Wlaschin’s Railway oriented programming for the exciting possibilities (video version here).

Now back to the original point of my post. Try putting the above Result enum into the Playground or your project code (that’s what I did immediately after reading about it…). Hint: It will not work! From my understanding, this is because the compiler doesn’t know how much memory to allocate for the generic type in the enum.

Hopefully this will be fixed in future versions of Swift, but for now the workout is to “Box” your generic type – in other words, wrap it in a class.

final class Box<T> {
    let value: T
    
    init(value: T) {
        self.value = value
    }
}

enum Result<T> {
    case Success(Box<T>)
    case Failure(NSError)
}

So now, you can use the result enum as follows:

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let result = Result.Success(Box(value: "hello"))
        
        handleResult(result)
    }
    
    func handleResult(result: Result<String>) {
        switch result {
        case .Success(let box):
            println(box.value)
        case .Failure(let error):
            println(error.description)
        }
    }
}

This type of Box pattern is useful to know in general, especially when working with generics.

For better understanding of actual Result pattern code (vs just theory) in Swift, make sure to check out the Result library on Github here.

Happy to hear additional thoughts and explanations about the Result enum and the Box pattern in the comments!

Enjoy the article? Join over 17,500+ Swift developers and enthusiasts who get my weekly updates.

  • bontoJR

    Nice! If you are interested, I wrote about introducing latency using Result, creating basically a Future:
    http://sideeffects.xyz/latency-as-effect-in-swift.html

  • Thierry Darrigrand

    You can also box the generic type in a closure or in an array. For example,with a closure:

    enum Result{
    case Success(()->T)
    case Failure(NSError)
    }

    let result:Result = Result.Success({“Hello”})

    switch result {
    case let .Success(t):
    println(t())
    case .Failure (let error):
    println(error)
    }

    With an array:

    enum Result{
    case Success([T])
    case Failure(NSError)
    }

    let result = Result.Success([“Hello”])

    switch result {
    case let .Success(successes):
    println(successes[0])
    case .Failure (let error):
    println(error)
    }

  • Thomas Sempf

    I always wonder which error handling method should be preferred: result enums or callback closures, especially in asynchronous scenarios? Advantage which closures are that the different return paths can contain completely different return data. Obvious advantage which enums is a common call semantic throughout the code.