`diff Swift C++`: Strange case of `enum`

So far the biggest difference that I've encountered between modern C++ use (read: C++11 with its standard library for generic containers and reference counting, exception safety guarantees and so on) and Swift is enum.

enum in C++ is just an enumeration of values of different integral types. There is nothing fancy about it nor anything that you haven't seen in other languages like Java or C#.

enums in Swift are something completely different:

  • They can take values of string, char or any integer or floating-point type (fine)
  • They can take associated values of any type within the same enum instance (what?) or as Swift book puts it:

“much as unions or variants do in other languages”

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/cl/jEUH0.l

(aaaah...)

  • They allow you to not provide a direct raw value but instead let compile generate the internal representations in which case enum values are not convertible to raw values (unlike C/C++ where you can always cast them)
  • They can have computed properties and instance methods ("curiouser and curiouser")
  • They can provide initializers (I'll just stop now)
  • They can be extended.
  • They can adopt protocols.
  • They can be pattern matched in switch statemens (another seemingly-similar-yet-rather-different facility than the one called switch in other mainstream languages)
  • They can be generic types (!!)

That's lot to digest. To make it easy I've simply stopped thinking of these as enums but rather as a specialized type of classes that exibit some minor enum characteristics as well.

IpAddress example

During my experimentation I came up with the following IP address enum example:

enum IpAddress : Printable {

Only the following lines are the actual enum values:

    //  IPv4 address is 4 bytes long
    case v4(Byte, Byte, Byte, Byte)
    //  IPv6 address is 8 words long
    case v6(Word, Word, Word, Word, Word, Word, Word, Word)

Here we can see how protocols are implemented as in other language constructs. At the same time this is obviously a property.

    //  Implementation of Printable protocol
    var description: String {
        switch self {

switch command can perform pattern matching which can extract the values associated to an enum value:

        case let .v4(b1, b2, b3, b4):
            return "\(b1).\(b2).\(b3).\(b4)"
        case let .v6(w1, w2, w3, w4, w5, w6, w7, w8):
            //  If I tried postfix formatting XCode would just continuously crash
            //  so at the end I left Words unformatted (that is... formatted in the
            //  decimal system)
            return "\(w1):\(w2):\(w3):\(w4):\(w5):\(w6):\(w7):\(w8)"
        }
    }

enums can have methods.

    //  Return the array of constituent address values.
    //  If IpAddress is IPv4 then convert Byte values to Word.
    func getArray() -> Word[] {
        switch self {
        case let .v4(b1, b2, b3, b4):

Unrelated to enums an example of mapping an array of Byte values to an array of Word values.

            //  Map the array of IPv4 values to a Word array.
            return [b1, b2, b3, b4].map { Word($0) }
        case let .v6(w1, w2, w3, w4, w5, w6, w7, w8):
            return [w1, w2, w3, w4, w5, w6, w7, w8]
        }
    }

We can even setup constant values of the very same enum.

    //  Constant to be used for IpV4 0.0.0.0
    static let ZeroV4 = IpAddress.v4(0, 0, 0, 0)
    //  Constant to be used for IpV4 127.0.0.1
    static let LoopbackV4 = IpAddress.v4(127, 0, 0, 1)
    //  Constant to be used for IpV6 0:0:0:0:0:0:0:0
    static let ZeroV6 = IpAddress.v6(0, 0, 0, 0, 0, 0, 0, 0)
    //  Constant to be used for IpV6 ::1
    static let LoopbackV6 = IpAddress.v6(0, 0, 0, 0, 0, 0, 0, 1)

}

This example doesn't illustrate the generics but the example in the Swift book (reemplimenting optional values with generic enum) is great.

A couple of final notes:

  • I failed to implement a default init - compiler simply wouldn't allow me to assign to self which was fine by me but left me without options. I even tried doing initialization delegation and at some point I managed to make it compile but it didn't work.
  • As I noted in the comments, I couldn't make hexadecimal formatting work with string interpolation - XCode would constantly crash on restart until I edited the playground source. It wasn't relevant for the example so I left it as it was.

Author

Ivan Erceg

Software shipper, successful technical co-founder, $1M Salesforce Hackathon 2014 winner