--- Title: Rust and Swift (ix) Subtitle: > Sum types (enums) and more on pattern matching Category: Tech Tags: [software development, listicles, rust, swift, rust-and-swift] Date: 2015-11-09 22:20 modified: 2019-06-22 10:55 Series: Title: Rust and Swift Part: 9 ... I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I'd be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. [(See all parts in the series.)][series] [series]: /rust-and-swift.html --- - Right off the bat when looking at the definitions for Swift's and Rust's `enum` types, a difference pops out: the use of the keyword `case` to introduce an enum member in Swift. In one sense, this overloads that keyword, but in another sense it's fine: pattern matching and enums go hand in hand, so the use in both cases is fairly natural. Rust doesn't have any special syntax to designate the elements of an enum; they're just separated by commas. - I am not at all shocked to find that Swift has a variant syntax for its unit type case declarations, where a single `case` keyword precedes a list of comma-separated cases defined on a single line. (At this point, I would be more surprised *not* to find a variant syntax for something in Swift!) - Something truly wonderful about both Rust and Swift: enumerated types aren't just wrappers around integer values. They're real types of their own. This is powerful. - Rust and Swift also share in having enumerated types that can hold values. The most prominent of these so far in the Swift book are optionals, the `Optional` enum type, corresponding very closely to Rust's `Option` type. Having had these for a bit in playing with Rust, and having gotten familiar with the utility of types like these while reading [_Maybe Haskell_]---a delightful book which introduces Haskell and functional programming using Haskell's `Maybe` type---I now miss them profoundly in languages which don't have them. (Which is to say: every language I use on a regular basis professionally: C, C++, Python, JavaScript, etc.). - Swift's enum types don't have integer values *by default*---but they can have them if you define a type and assign a value to each enum case at the definition. These "raw values" are distinct from the "associated values" noted just above. I expect these exist primarily for ease of interoperation with Objective-C. - ~~Rust doesn't have anything like this, at least that I can think of. The main place it would be useful would be for foreign function interfaces (as in Swift), and this is one of several such gaps in Rust,~~ along with the lack of a straightforward way to map to C's `union` types. ~~There are trade offs in terms of adding the functionality to the language, though, as it substantially increases the complexity of what an enum value can be, I think.~~ **Edit:** This was incorrect. From the [Rust Reference] section on [Enumerations]: > Enums have a discriminant. You can assign them explicitly: > > ```rust > enum Foo { > Bar = 123, > } > ``` > > If a discriminant isn't assigned, they start at zero, and add one for each variant, in order. > > You can cast an enum to get this value: > > ```rust > let x = Foo::Bar as u32; // x is now 123u32 > ``` > > This only works as long as none of the variants have data attached. If it were `Bar(i32)`, this is disallowed. - Initialization of Swift's raw-valued enum type is quite similar, and pleasantly so, to Python's initialization of enums. - In a surprising change from the usual, Swift's syntax for binding variable names when pattern matching against an enum is *more* verbose than Rust's, requiring the use of either a leading `let` on the `case` statement if all the elements are of the same type, or a `let` in front of each element otherwise: ```swift var matchedValue: String let matchee = 3.14159 switch matchee { case 3.14159: matchedValue = "pi" case _: matchedValue = "not pi" } ``` In Rust, a matched pattern can simply bind its value directly: ```rust let matchee = 3.14159; let matchedValue = match matchee { 3.14159 => "pi".to_string(), _ => "not pi".to_string() }; ``` - Swift has the ability to do recursive enumerations with its `indirect` type. This is conceptually interesting, but off the top of my head I can't think of a time when this would have been useful at any point since I started programming seven and a half years ago. The book's example of a recursive function aliasing arithmetic expressions is fine, but not particularly illuminating to me. I suspect, though, that it might make more sense if I were more familiar with pure functional programming paradigms. **Edit:** a friend [points out]: > Indirect enums are useful for recursive types in general. There are a lot of these: Lists, trees, and streams are the big ones that come to mind. - All those same lines: Rust does *not* have the ability to have recursive enumerations at present (or recursive `struct` types, for that matter), at least without heap-allocating with `Box` along the way. You *can* construct such a type, in other words, but you have to be explicit about how you're handling the memory, and it can't be stack-allocated. + For an example of a recursive enumeration type (as well as an interesting/hilarious example of how you can easily confuse the compiler if you do this wrong), see [this Rust forum post][forum]. + For some discussion on stack- and heap-allocated memory in Rust, I'll shamelessly promote my Rust podcast, [New Rustacean]: take a listen to [e005: Allocate it where?][e005] [_Maybe Haskell_]: https://gumroad.com/l/maybe-haskell [Rust Reference]: https://doc.rust-lang.org/reference.html [Enumerations]: https://doc.rust-lang.org/reference.html#enumerations [points out]: https://alpha.app.net/jws/post/65990633 [forum]: https://users.rust-lang.org/t/recursive-enum-types/2938 [New Rustacean]: http://www.newrustacean.com [e005]: http://www.newrustacean.com/show_notes/e005/index.html --- - [**Previous:** Functions, closures, and an awful lot of Swift syntax.][8] - [**Next:** Classes and structs (product types), and reference and value types.][10] [8]: http://v4.chriskrycho.com/2015/rust-and-swift-viii.html [10]: http://v4.chriskrycho.com/2015/rust-and-swift-x.html