Enums in Swift

Our enum type ServerState has an underlying Int type.

enum ServerState: Int {
    case idle
    case connected
    case error
    case retrying
}

The possible values for ServerState are defined as constants. The Int raw value of idle is 0, connected is 1, error is 2, and retrying is 3.

By implementing the CustomStringConvertible protocol, values of ServerState can be printed out or converted to strings.

This can get cumbersome if there are many possible values. In such cases, the CustomStringConvertible protocol can be used to automate the process.

extension ServerState: CustomStringConvertible {
    var description: String {
        switch self {
        case .idle:
            return "idle"
        case .connected:
            return "connected"
        case .error:
            return "error"
        case .retrying:
            return "retrying"
        }
    }
}

If we have a value of type Int, we cannot pass it to transition - the compiler will complain about type mismatch. This provides some degree of compile-time type safety for enums.

func main() {
    let ns = transition(state: .idle)
    print(ns)

    let ns2 = transition(state: ns)
    print(ns2)
}

main()

transition emulates a state transition for a server; it takes the existing state and returns a new state.

func transition(state: ServerState) -> ServerState {
    switch state {
    case .idle:
        return .connected
    case .connected, .retrying:
        // Suppose we check some predicates here to determine the next state...
        return .idle
    case .error:
        return .error
    @unknown default:
        fatalError("unknown state: \(state)")
    }
}

To run the program, save the code in a file with .swift extension and use swift to execute it:

$ swift Enums.swift
connected
idle