[swift-evolution] [proposal] Treat (case .Foo = bar) as a Boolean expression

Sam Dods sam at theappbusiness.com
Tue May 10 06:33:02 CDT 2016


I propose that (case .Foo = bar) should be treated as an expression with a Boolean value, so the result can be set to a variable or returned from a method.

Considering the following enumeration:

enum Bar {
  case foo(name: String)
  case notFoo
  case unknownFoo
}

Instead of having to do the following:

func isBarFoo(bar: Bar) -> Bool {
    if case .Foo = bar {
        return true
    }
    return false
}

We could simply do the following:

func isBarFoo(bar: Bar) -> Bool {
    return (case .Foo = bar)
}

We could also do things like this:

let isBarFoo = (case .Foo = bar)
XCTAssert(isBarFoo)

Of course, this change is only required for enumerations that don't have a raw value type (String, Int, etc).

It assumes the developer does not care what the associated value is, which could lead to issues. But this is already the case with the `if case ... return true/false` syntax. So it is not a degrading feature, just a more concise syntax for something that already exists.

Something to consider is whether `case let ...` could be treated as an expression in the same way. For example:

if (case let .Foo(name) = bar) && name == "Alan" {
  return true
}
return false

The above could be simplified to:

return (case let .Foo(name) = bar) && name == "Alan"

Due to the way AND-ed expression results are computed at runtime, the second expression would not be computed unless the first was true, so `name` must have a value. The compiler would know that when OR-ing expressions, the second expression is only computed if the first expression was false, so `name` definitely doesn't have a value:

return (case let .Foo(name) = bar) || name == "Alan"

I would expect a compiler error similar to `Variable declared in 'guard' condition is not usable in its body`.

What does everyone think of this? It would have no impact on existing code. 


alternative, not proposing...

An alternative would be defaulting what equality means for enumerations, such that the `==` operator is automatically defined for enumerations in the following way:

func ==(lhs: Bar, rhs: Bar) -> Bool {
    if case rhs = lhs {
        return true
    }
    return false
}

However, I think that having a default implementation for enum is a bad idea, because it's adding default behaviour that the developer might not know about. And this could lead to a less experienced developer making a mistake when comparing two enum values with associated values. Developers that know the `if case ...` syntax are already expected to understand that they are ignoring the associated value and they can use `if case let ...` if they care about the associated value. So my proposal is in-line with an existing expectation.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160510/f483081d/attachment.html>


More information about the swift-evolution mailing list