<div dir="ltr"><div>It feels like it solves my current problem in a way that&#39;s almost as undesirable as the current solution. Say I have:</div><div><br></div><div><div>Enum A {</div><div>   case x(String?)</div><div>   case y(String)</div><div>}</div></div><div><br></div><div>Right now I have code like this peppered throughout my code, which I think we can agree is pretty undesirable:</div><div><br></div><div>if let case .x = value { return true } else { return false }</div><div><br></div><div>I actually think that new syntax would be worse. It&#39;s not obvious what this does:</div><div><br></div><div>if let string = value.getX() {<br></div><div>    return string != nil   </div><div>} else {</div><div>    return false</div><div>}</div><div><br></div>Even aside from readability, it strikes me as very weird that we have clean syntax for cases that ignore associated values inside of switch, if and guard statements, but outside of them we need to always write code around the associated value even when the associated values don&#39;t matter to what we&#39;re trying to do. I&#39;m not going to pretend it&#39;s something I hit every day, but it&#39;s something I do *fairly* often, and it always feels like I&#39;m fighting the language to do it.<div><br></div><div>Having an isX() would be a big improvement, and I think we&#39;d happily take it. That being said, any of these are the code I would ideally want to write:</div><div><br></div><div>let a: A = .x(&quot;String&quot;)</div><div><br></div><div>a.matches(.x) // true<br></div><div>a.matches(.x(_)) // true</div><div>a.matches(.x(&quot;Taco&quot;) // false</div><div><br></div><div>or</div><div><br></div><div>case(of: a) == .x // true (my personal favorite)</div><div><br></div><div>or</div><div><br></div><div>case a == .x // true</div><div><div><div><div><div><br></div></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Dec 20, 2017 at 3:11 PM Chris Lattner &lt;<a href="mailto:clattner@nondot.org">clattner@nondot.org</a>&gt; wrote:<br></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"><div><blockquote type="cite"><div>On Dec 20, 2017, at 2:12 PM, Ethan Diamond &lt;<a href="mailto:ethanjdiamond@gmail.com" target="_blank">ethanjdiamond@gmail.com</a>&gt; wrote:</div><br class="m_5774033850724332857Apple-interchange-newline"><div><div dir="ltr">Would that synthesize an isY() even though .Y has an associated value there?</div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div>I’m not aware of a concrete design for this idea.  The details would definitely need to be figured out, but I don’t see why a double optional is itself a problem.</div></div><div style="word-wrap:break-word"><div><br></div><div>-Chris</div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div dir="ltr"><div><br><div>enum E {</div><div>    case X</div><div>    case Y(Int?)</div><div>}</div><div><br></div><div>If I had to run that through getY() -&gt; Int??, it still wouldn&#39;t be quite what I was looking for with regards to intent. If you are planning an doing an isY though, that would work for most cases where you&#39;re evaluating for a given enum and know what it is beforehand. Even so that wouldn&#39;t work for a case, for example, where I&#39;m trying to see if two enums are the same case, and don&#39;t necessarily care if they&#39;re equal.</div></div><div><br></div><div>let value1 = E.Y(1)</div><div>let value2 = E.Y(2)<br></div><div><br></div><div>value1 == value2 // false</div><div>value1 [is the same case as] value 2 // how do I get this?</div><div><br></div><div>This would be useful, say, if I was trying to generate a diff of two arrays of enums, which I occasionally do for table / collection views to figure out inserts/removals/updates.</div><div><br></div><div>I don&#39;t necessarily know if it&#39;s feasible, but it would be really great to have something like a Case metatype, the same way we have type(of: ). It would be great to have a case(of: ) that we can evaluate against the shorthand like we do in switch statements. </div><div><br></div><div>Ex: </div><div><br></div><div>case(of: value1) == .Y // true</div><div>case(of: value1) == .X // false</div><div>case(of: value1) == case(of: value2) // true</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Dec 20, 2017 at 1:31 PM Chris Lattner &lt;<a href="mailto:clattner@nondot.org" target="_blank">clattner@nondot.org</a>&gt; wrote:<br></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">In the past, we’ve discussed synthesizing predicate members onto enums.  E.g. given:<div><br></div><div>enum E {</div><div>  case X</div><div>  case Y(Int)</div><div>}</div><div><br></div><div>you’d get something like:</div><div><br></div><div>extension E {</div><div>  func isX() -&gt; Bool { return self == .X }</div><div>  func getY() -&gt; Int? { … }</div><div>}</div><div><br></div><div>which would solve the client side of this nicely.</div><div><br></div><div>-Chris</div><div><br></div><div><br></div><div><br><div><blockquote type="cite"></blockquote></div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div>On Dec 20, 2017, at 11:24 AM, Ethan Diamond via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_5774033850724332857m_7271590183074468783Apple-interchange-newline"></blockquote></div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div><div dir="ltr">Sorry all for attaching the original post to the Non-Exhaustive enums thread. I&quot;m moving it down to it&#39;s own thread. <div><div><br></div><div>My understanding is I&#39;m not allowed to write up a proposal unless I have the time to implement it. Is that still true? This is a major pain point for me to avoid having to write things like this:</div><div><div>





<br class="m_5774033850724332857m_7271590183074468783webkit-block-placeholder"></div><p class="m_5774033850724332857m_7271590183074468783inbox-inbox-p1">if<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> </span>case<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> .</span><span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s2">search</span><span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> = presenter.</span><span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s2">state</span><span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> { </span>return<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> </span>true<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> } </span>else<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> { </span>return<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> </span>false<span class="m_5774033850724332857m_7271590183074468783inbox-inbox-s1"> }</span></p></div><div>Side note: Thanks Kevin, didn&#39;t know you could nest enums in switches like that. Super helpful!<br></div><div><br></div><div>------------------------------------------------------</div><div><pre style="white-space:pre-wrap">I thought I would add another case that isn’t possible with current syntax (so far as I’m aware).  You can’t negate the comparison to do something for all cases except a particular case.  You have to have an empty if block and use the else block, or have an empty case in a switch statement and use the default.

enum Enum {
  case a(param: String)
  case b(param: String)
  case c(param: String)
}

let enumeration: Enum = .a(param: &quot;Hi&quot;)

if !(case .a = enumeration) {
  // Do something
}

— Charles

&gt;<i> On Dec 20, 2017, at 9:55 AM, Kevin Nattinger via swift-evolution &lt;<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">swift-evolution at swift.org</a>&gt; wrote:
</i>&gt;<i> 
</i>&gt;<i> I agree this would be useful. At the moment I have to hack around it with things like `var isFoo: Bool { if case .foo = self …`* with cases I commonly need, but this is definitely a feature that has come up before and I support. It is potentially related to getting the values through an accessor, which has also come up several times.
</i>&gt;<i> 
</i>&gt;<i> Sidenote, your `switch` example is actually trivial with existing syntax:
</i>&gt;<i> 
</i>&gt;<i> switch enumeration {
</i>&gt;<i> case .a(.c(let param)): // or just .a(.c) if you don&#39;t need the value
</i>&gt;<i>     print(param)
</i>&gt;<i> default:
</i>&gt;<i>     break
</i>&gt;<i> }
</i>&gt;<i> 
</i>&gt;<i> I use this from time to time switching over, e.g., optional enums.
</i>&gt;<i> 
</i>&gt;<i> *: ugliest syntax ever, and it can&#39;t even be used as a standalone expression.
</i>&gt;<i> 
</i>&gt;<i> 
</i>&gt;&gt;<i> On Dec 20, 2017, at 8:44 AM, Ethan Diamond via swift-evolution &lt;<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">swift-evolution at swift.org</a> &lt;mailto:<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">swift-evolution at swift.org</a>&gt;&gt; wrote:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> Hello everyone,
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> One major pain point I&#39;ve run into with Swift is the inability to evaluate the case of an enum that has associated values in a way that just returns a bool. We&#39;ve been given the ability in a switch statement:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> enum Enum {
</i>&gt;&gt;<i>    case a(param: String)
</i>&gt;&gt;<i>    case b(param: String)
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> let enumeration: Enum = a(param: &quot;Hi&quot;)
</i>&gt;&gt;<i> switch enumeration {
</i>&gt;&gt;<i>     case a:
</i>&gt;&gt;<i>       // Do something
</i>&gt;&gt;<i>     case b:
</i>&gt;&gt;<i>       // Do something
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> We&#39;e been given the ability in the context of an if statement:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> enum Enum {
</i>&gt;&gt;<i>    case a(param: String)
</i>&gt;&gt;<i>    case b(param: String)
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> let enumeration: Enum = a(param: &quot;Hi&quot;)
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> if case .a = enumeration { 
</i>&gt;&gt;<i>     // Do something
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> But without a basic was of getting a bool for if an enum is a given case, here&#39;s a list of things I can&#39;t do:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> Where statements:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> enum Enum {
</i>&gt;&gt;<i>    case a(param: Enum2)
</i>&gt;&gt;<i>    case b(param: Enum2)
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> enum Enum2 {
</i>&gt;&gt;<i>     case c(param: String)
</i>&gt;&gt;<i>     case d(param: String)
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> let enumeration: Enum = a(param: &quot;Hi&quot;)
</i>&gt;&gt;<i> switch enumeration {
</i>&gt;&gt;<i>     case a(let inner) where [INNER CASE IS .c]
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> ---------
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> Filter an array for a certain case:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> Expertly explained by Erica Sadun here: <a href="http://ericasadun.com/2017/01/31/challenge-filtering-associated-value-enumeration-arrays/" target="_blank">http://ericasadun.com/2017/01/31/challenge-filtering-associated-value-enumeration-arrays/</a> &lt;<a href="http://ericasadun.com/2017/01/31/challenge-filtering-associated-value-enumeration-arrays/" target="_blank">http://ericasadun.com/2017/01/31/challenge-filtering-associated-value-enumeration-arrays/</a>&gt;
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> ---------
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> Nicely set a UIButton to hidden if an enum is a certain case:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> enum State {
</i>&gt;&gt;<i>     case `default`
</i>&gt;&gt;<i>     case searching(results: [Result])
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> myButton.isHidden = [STATE IS .searching]
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> ---------
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> I&#39;ve run into this issue a ton of times because I tend to represent my views a State enums. I haven&#39;t seen anything on the board for plans for solving this issue, thought. Has there been any discussion about addressing it? Ideally I&#39;d be able to do this:
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> enum Enum {
</i>&gt;&gt;<i>    case a(param: String)
</i>&gt;&gt;<i>    case b(param: String)
</i>&gt;&gt;<i> }
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> let enumeration: Enum = a(param: &quot;Hi&quot;)
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> case .a = enumeration // Bool
</i>&gt;&gt;<i> case .a(let param) = enumeration // Bool, assigns &quot;Hi&quot; to &quot;param&quot;
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> Thanks!
</i>&gt;&gt;<i> Ethan
</i>&gt;&gt;<i> 
</i>&gt;&gt;<i> _______________________________________________
</i>&gt;&gt;<i> swift-evolution mailing list
</i>&gt;&gt;<i> <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">swift-evolution at swift.org</a> &lt;mailto:<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">swift-evolution at swift.org</a>&gt;
</i>&gt;&gt;<i> <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a>
</i>&gt;<i> 
</i>&gt;<i> _______________________________________________
</i>&gt;<i> swift-evolution mailing list
</i>&gt;<i> <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">swift-evolution at swift.org</a>
</i>&gt;<i> <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></i></pre></div></div></div></div></blockquote></div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div>
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br></div></div></blockquote></div>
</div></blockquote></div><br></div></blockquote></div>