The last time I was in this situation, I resolved it by having a shadow enum 
with the same cases but without any associated value.

I also created shadow enums for error enums. The shadow enum wouldn't have any 
associated value, and Int as RawValue, and I would also use it as an error code 
when converting to NSError.

But it's not really fun to maintain.

Pierre

> Le 18 janv. 2017 à 05:51, Andy Chou via swift-evolution 
> <[email protected]> a écrit :
> 
> I see your point about conformances. In my example, AuthenticationResponse 
> isn't a generic type, so the conformances spec won't apply.
> 
> I'll go out on a limb and say that 80%+ of the use cases for equality will be 
> to distinguish enum cases, not the associated values.
> 
> I do like your proposal though. In the thread talking about it someone 
> mentioned a 'derived' keyword to specify conformance and derivation 
> simultaneously. I like the idea of being able to say:
> 
>       enum AuthenticationResponse: derived Equatable { ... }
> 
> Still, even with derived conformance, it can still be very useful to be able 
> to test against specific enum cases when the associated values aren't 
> Equatable. Maybe this example would make it clearer:
> 
> ```
> enum OpaqueResponse {
>       case success(OpaqueResult)
>       case failure
> }
> ```
> 
> If OpaqueResult is from a library module and its implementation uses private 
> variables, it may not be easy to make it conform to Equatable. Yet, it would 
> be nice to be able to say:
> 
> ```
> let result: OpaqueResponse = request()
> if request == .failure  { ... }
> ```
> 
> A more realistic example comes from the world of Rx, where the original issue 
> I have came from:
> 
> ```
> let result: Observable<OpaqueResponse> = request()
> 
> result.filter { $0 == .failure } ...
> result.filter { $0 == .success } ...
> 
> // The best we can do today looks more like:
> result.filter { if case .failure = $0 { return true} else { return false } }
> result.filter { $0.isFailure }    // but we have to define isFailure ourselves
> 
> // There's a similar issue with assertions
> if case .failure = result { assert(false) }
> assert({ if case .failure = result { return true } else { return false } }())
> ```
> 
> I agree it's less of an issue with test cases. The issue arises when we want 
> a Bool valued expression...
> 
> Andy
> 
>> On Jan 17, 2017, at 6:38 PM, Tony Allevato <[email protected]> wrote:
>> 
>> 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 
>>> <[email protected]> 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 <[email protected]> 
>>>> 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 
>>>>> <[email protected]> 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
>>>>> [email protected]
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to