<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><div><span style="background-color: rgba(255, 255, 255, 0);">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.</span></div><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">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.</span></div><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">But it's not really fun to maintain.</span></div><br>Pierre</div><div><br>Le 18 janv. 2017 à 05:51, Andy Chou via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> a écrit :<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8">I see your point about conformances. In my example, AuthenticationResponse isn't a generic type, so the conformances spec won't apply.<div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>enum AuthenticationResponse: derived Equatable { ... }</div><div class=""><br class=""></div><div class=""><div class="">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:</div></div><div class=""><br class=""></div><div class="">```</div><div class="">enum OpaqueResponse {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>case success(OpaqueResult)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>case failure</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class="">```</div><div class="">let result: OpaqueResponse = request()</div><div class="">if request == .failure { ... }</div><div class="">```</div><div class=""><br class=""></div><div class="">A more realistic example comes from the world of Rx, where the original issue I have came from:</div><div class=""><br class=""></div><div class="">```</div><div class="">let result: Observable<OpaqueResponse> = request()</div><div class=""><br class=""></div><div class="">result.filter { $0 == .failure } ...</div><div class="">result.filter { $0 == .success } ...</div><div class=""><br class=""></div><div class="">// The best we can do today looks more like:</div><div class="">result.filter { if case .failure = $0 { return true} else { return false } }</div><div class="">result.filter { $0.isFailure } // but we have to define isFailure ourselves</div><div class=""><div class=""><br class=""></div><div class="">// There's a similar issue with assertions</div><div class="">if case .failure = result { assert(false) }</div><div class="">assert({ if case .failure = result { return true } else { return false } }())</div><div class="">```</div><div class=""><br class=""></div><div class="">I agree it's less of an issue with test cases. The issue arises when we want a Bool valued expression...</div><div class=""><br class=""></div><div class="">Andy</div><div class=""><br class=""></div><div class=""><div class=""><div><blockquote type="cite" class=""><div class="">On Jan 17, 2017, at 6:38 PM, Tony Allevato <<a href="mailto:tony.allevato@gmail.com" class="">tony.allevato@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">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 <<a href="https://gist.github.com/allevato/2fd10290bfa84accfbe977d8ac07daad" class="gmail_msg" target="_blank">https://gist.github.com/allevato/2fd10290bfa84accfbe977d8ac07daad</a>> in another thread, but as Robert mentioned, the missing piece is how users opt in/out of it.<div class=""><br class=""></div><div class="">If you just want to check the case of an enum in a test, what about this?</div><div class=""><br class=""></div><div class=""> enum Foo {</div><div class=""> case bar</div><div class=""> case baz(Int)</div><div class=""> }</div><div class=""> let foo = Foo.baz(5)</div><div class=""> guard case .baz = foo else { XCTFail("expected baz"); return }</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Jan 17, 2017 at 5:59 PM Andy Chou via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg">Yes, here's a reference to the conditional conformance proposal which was accepted:<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md</a></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">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.</div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Andy</div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Jan 17, 2017, at 5:45 PM, Robert Widmann <<a href="mailto:devteam.codafi@gmail.com" class="gmail_msg" target="_blank">devteam.codafi@gmail.com</a>> wrote:</div><br class="gmail_msg m_-8364123832418668739Apple-interchange-newline"><div class="gmail_msg"><div class="gmail_msg">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?<br class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg">On Jan 17, 2017, at 7:15 PM, Andy Chou via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:<br class="gmail_msg"><br class="gmail_msg">Enums with associated values can be very useful in Swift, but once you add associated values you lose some properties, especially equality:<br class="gmail_msg"><br class="gmail_msg">```<br class="gmail_msg">enum AuthenticationResponse {<br class="gmail_msg"> case success<br class="gmail_msg"> case alert(Alert)<br class="gmail_msg"> case reauthenticate<br class="gmail_msg">}<br class="gmail_msg">```<br class="gmail_msg"><br class="gmail_msg">Testing for a specific case requires a switch statement or the if pattern match syntax:<br class="gmail_msg"><br class="gmail_msg"><span class="m_-8364123832418668739Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>if case .success = response { … }<br class="gmail_msg"><br class="gmail_msg">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:<br class="gmail_msg"><br class="gmail_msg">```<br class="gmail_msg">enum AuthenticationResponse {<br class="gmail_msg"> case success<br class="gmail_msg"> case alert(Alert)<br class="gmail_msg"> case reauthenticate<br class="gmail_msg"><br class="gmail_msg"> var isSuccess: Bool {<br class="gmail_msg"> if case .success = self {<br class="gmail_msg"> return true<br class="gmail_msg"> } else {<br class="gmail_msg"> return false<br class="gmail_msg"> }<br class="gmail_msg"> }<br class="gmail_msg"><br class="gmail_msg"> var isReauthenticate: Bool {<br class="gmail_msg"> if case .reauthenticate = self {<br class="gmail_msg"> return true<br class="gmail_msg"> } else {<br class="gmail_msg"> return false<br class="gmail_msg"> }<br class="gmail_msg"> }<br class="gmail_msg"><br class="gmail_msg"> var isAlert: Bool {<br class="gmail_msg"> if case .alert(_) = self {<br class="gmail_msg"> return true<br class="gmail_msg"> } else {<br class="gmail_msg"> return false<br class="gmail_msg"> }<br class="gmail_msg"> }<br class="gmail_msg">}<br class="gmail_msg">```<br class="gmail_msg">Any suggestions better than writing out each of these functions explicitly?<br class="gmail_msg"><br class="gmail_msg">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:<br class="gmail_msg"><br class="gmail_msg"><span class="m_-8364123832418668739Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>assert(response == .success)<br class="gmail_msg"><br class="gmail_msg">This is perfectly intelligible and I would argue that equality should be defined for enums with associated values omitted:<br class="gmail_msg"><br class="gmail_msg"><span class="m_-8364123832418668739Apple-tab-span gmail_msg" style="white-space:pre-wrap">        </span>assert(response == .alert)<br class="gmail_msg"><br class="gmail_msg">Here we are ignoring the associated values, and merely checking if the enum case is the same.<br class="gmail_msg"><br class="gmail_msg">Andy<br class="gmail_msg"><br class="gmail_msg">_______________________________________________<br class="gmail_msg">swift-evolution mailing list<br class="gmail_msg"><a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg"></blockquote><br class="gmail_msg"></div></div></blockquote></div><br class="gmail_msg"></div></div>_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>
</div></blockquote></div><br class=""></div></div></div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>