Hacker News new | ask | show | jobs
by masklinn 3565 days ago
Your cases 2 and 3 are pattern matches. It's perfectly fine to use regular equality with optionals (case 2) or enums (case 3), but in that case you're not matching a pattern you're comparing two specific values, and you need the types to be equatable[0] (enums aren't by default, though optionals are if they contain an equatable value).

* you can write "foobar == .someEnum" if you've defined "==" for your enum type (in Rust that's a deriving(Eq) away, sadly Swift doesn't seem to have deriving):

    // requires conforming to Equatable, and implementing
    // requires func ==(a: Foo, b: Foo) -> Bool somewhere
    // if the enum has associated data[1]
    let v = Foo.Bar;
    if v == .Bar {
        print("ok")
    }
you can also do that with optionals by default:

    let w = Optional.some(3)
    if w == .some(4) {
        print("ok")
    }
* `let a = b && thing` doesn't make sense because `let a = b` is not a boolean value it's a pattern match. That's why you have a separate guard (the where) and have to write `let a = b where thing`, this is what happens in pretty much every language with pattern-matching (though syntax may vary)

* `let d == f` makes no sense whatsoever, though as previously noted `f == .some(d)` works

* you can compose `if case` and `if let` in, since both are pattern matches, `if case .Bar = v, let b = w` works fine

If you're getting lost with that, use the regular `if` for boolean stuff, and a full `switch` for all patterns. There, I fixed it.

That aside, I do agree Swift's syntax is convoluted and complex. Part of that comes from `if let` being special-cased to optionals, which is convenient when you're working specifically with optionals but means a separate syntax for other enums.

On the other hand, most languages with pattern-matching don't provided a "conditional-ish" version, Haskell's `if` works solely on booleans, if you want to work with patterns you have to break out the full `case`. Rust lifted `if let` from Swift (with different semantics) because it was such a neat idea.

[0] http://www.andrewcbancroft.com/2015/07/01/every-swift-value-...

[1] for trivial enums (no associated data, though they can have a rawValue), you can just `enum Foo: Equatable` and it'll get a proper implementation; for the rest you have to implement == yourself: http://www.jessesquires.com/swift-enumerations-and-equatable...

1 comments

> you can write "foobar == .someEnum" if you've defined "==" for your enum type

Why wouldn't enums be equatable by default? Why rely on a user implementation of ==? Enums, even with associated data, are rather obvious values, aren't they?

> Enums, even with associated data, are rather obvious values, aren't they?

Associated data can be completely arbitrary (and thus possibly not equatable), I expect the designers would rather people use pattern matching instead of the more error-prone boolean constructs, and likely they don't want to add "unnecessary" capabilities so if the developer don't need equatable enums there's no reason to make them and developers can ask for it when they need it.

Rust makes the same choice, so does haskell, though in both enum/data equality is just a derive/deriving away.