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

Patrick Smith pgwsmith at gmail.com
Tue May 10 09:18:09 CDT 2016


I like the idea of a boolean expression! I think it is cleaner; the required if statement is a pain.

For the second idea, I’ve wondered if there could be some way of unwrapping the associated values:

case .foo(?) = bar

It would produce an optional. This would let you do:

let isAlan = (case .foo(?) = bar) == “Alan”


There’s also force unwrap:

let name = (case .foo(!) = bar)


Even better would be a way of unwrapping multiple values of the same type:

enum Bar {
  case foo(name: String)
  case goo(kind: GooKind, name: String)

  var name: String {
    return case .foo(!), .goo(_, !) = bar
  }
}


> On 10 May 2016, at 9:33 PM, Sam Dods via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 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.
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


More information about the swift-evolution mailing list