[swift-evolution] Testing enum cases with associated values

Tony Allevato tony.allevato at gmail.com
Tue Jan 17 20:38:38 CST 2017


Conditional conformances doesn't solve enum equality though, because there
likely won't be a way to utter "enum Foo : Equatable where <all types
across all associated value payloads are Equatable>" with the generics
syntax that's available, and conformance alone wouldn't be able to derive
the implementation. It'll require some work on the compiler's part to
generate the right implementation—I mentioned a draft proposal I wrote a
while back for auto-equality of enums and structs where all the components
are equatable <
https://gist.github.com/allevato/2fd10290bfa84accfbe977d8ac07daad> in
another thread, but as Robert mentioned, the missing piece is how users opt
in/out of it.

If you just want to check the case of an enum in a test, what about this?

    enum Foo {
      case bar
      case baz(Int)
    }
    let foo = Foo.baz(5)
    guard case .baz = foo else { XCTFail("expected baz"); return }

The "return" being required isn't ideal because XCTFail doesn't return
Never, but other than that it's not *horrible*. You can do whatever pattern
matching you need to use or ignore associated values as part of your
comparison.


On Tue, Jan 17, 2017 at 5:59 PM Andy Chou via swift-evolution <
swift-evolution at swift.org> wrote:

> Yes, here's a reference to the conditional conformance proposal which was
> accepted:
>
>
> https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
>
> But as I mention in my post, there are cases it doesn't handle.
> Specifically, when the associated types for an enum aren't equatable
> themselves, it's still possible to define equality on the enum cases
> without associated values.
>
> Andy
>
> On Jan 17, 2017, at 5:45 PM, Robert Widmann <devteam.codafi at gmail.com>
> wrote:
>
> Automatic “equatability” of aggregates that contain equatable members has
> been discussed on this list quite a few times.  (I think I had a branch at
> one point that was exploring this kind of deriving mechanism… It seems to
> be lost to the sands of time).  Everybody seems to agree that it’s a
> worthwhile feature, but there needs to be thought put into how it is
> exposed to the end user.  e.g. Should we continue with silently
> implementing these protocols if we can, or should there be some kind of
> annotation to tell the compiler to only synthesize what the user wants?
>
> On Jan 17, 2017, at 7:15 PM, Andy Chou via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Enums with associated values can be very useful in Swift, but once you add
> associated values you lose some properties, especially equality:
>
> ```
> enum AuthenticationResponse {
>   case success
>   case alert(Alert)
>   case reauthenticate
> }
> ```
>
> Testing for a specific case requires a switch statement or the if pattern
> match syntax:
>
> if case .success = response { … }
>
> But while this works well for control flow, it doesn’t work well for cases
> where we want a Bool, such as assert(). There are also common situations
> with lists and libraries like RxSwift where a filtering function uses a
> Bool valued closure. In these situations the best we can do is write
> functions like:
>
> ```
> enum AuthenticationResponse {
>   case success
>   case alert(Alert)
>   case reauthenticate
>
>   var isSuccess: Bool {
>       if case .success = self {
>           return true
>       } else {
>           return false
>       }
>   }
>
>   var isReauthenticate: Bool {
>       if case .reauthenticate = self {
>           return true
>       } else {
>           return false
>       }
>   }
>
>   var isAlert: Bool {
>       if case .alert(_) = self {
>           return true
>       } else {
>           return false
>       }
>   }
> }
> ```
> Any suggestions better than writing out each of these functions explicitly?
>
> The conditional conformances proposal coming in Swift 4 solves some of
> this issue, but not completely. If Alert isn’t Equatable, it is still
> useful to test whether the result is .success.  For example:
>
> assert(response == .success)
>
> This is perfectly intelligible and I would argue that equality should be
> defined for enums with associated values omitted:
>
> assert(response == .alert)
>
> Here we are ignoring the associated values, and merely checking if the
> enum case is the same.
>
> Andy
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> 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/20170118/7bacecce/attachment.html>


More information about the swift-evolution mailing list