<div dir="ltr">I'd like to spin this a slightly different way.<div><br></div><div>While they're not exactly the same as structs because the compiler has separate logic for exhaustiveness checking, enum cases have some interesting properties that make them relatable:</div><div><br></div><div>* A case without a payload is like a static read-only property on the enum type that is equal to a value of that type.</div><div>* A case with a payload is like a static function on the enum type that creates and returns a value of that type.</div><div><br></div><div>The second point is interesting because if you have:</div><div><br></div><div>```</div><div>enum Foo {</div><div> case bar(Int)</div><div>}</div><div>```</div><div><br></div><div>and you reference "Foo.bar" without a payload, what you get back is a function of type (Int) -> Foo.</div><div><br></div><div>So instead of casting your example as "a protocol can be enum-constrained and must contain certain cases", what if enums could just have their conformance fall out naturally from the bullet point observations above?</div><div><br></div><div>In other words, your example protocol could be:</div><div><br></div><div>```</div><div>protocol Result {</div><div> associatedtype Payload</div><div> static func success(_ p: Payload) -> Self</div><div> static func failure(_ e: Error) -> Self</div><div>}</div><div>```</div><div><br></div><div>and the cases provide the conformance without having to do anything extra:</div><div><br></div><div>```</div><div>enum UserParseResult: Result {</div><div> typealias Payload = User // can be omitted if it's inferred</div><div> case success(User)</div><div> case failure(Error)</div><div>}</div><div>```</div><div><br></div><div>Now there's a caveat here worth discussing: would the intention of an "enum-constrained protocol" be to define the *only* cases it can have, or just the minimal set? The former would let you do some interesting generic protocol-constrained exhaustive pattern matching. However, given that no other use of protocols defines an *exact* set (you don't say these are the *only* methods/properties that a conforming type can implement), I think it would be a hard sell to apply a stronger restriction specifically to enums. In any case, it feels to me like an enum restricted to "only these exact cases" calls more for a generic enum rather than a protocol-based solution.</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Oct 21, 2016 at 9:39 AM T.J. Usiyan via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">I would like the ability to specify that something is an enum so that I could model a generic `Result` type. <div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">```</div><div class="gmail_msg">protocol Result : enum {</div><div class="gmail_msg"> associatedtype Payload</div><div class="gmail_msg"> case success(Payload)</div><div class="gmail_msg"> case failure(Error)</div><div class="gmail_msg">}</div><div class="gmail_msg">```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">the basic idea being that I could then, while conforming, state which cases in the concrete type serve as the protocol's case. I don't have a great vision for the syntax of spelling this conformance so I will make this painfully verbose to be clear</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">```</div><div class="gmail_msg">enum UserParseResult {</div><div class="gmail_msg"> case success(User)</div><div class="gmail_msg"> case failure(Error)</div><div class="gmail_msg">}</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">extension UserParseResult : Result {</div><div class="gmail_msg"> protocol(Result) case success = UserParseResult.success</div><div class="gmail_msg"> protocol(Result) case failure = UserParseResult.failure<br class="gmail_msg"></div><div class="gmail_msg">}</div><div class="gmail_msg">```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The benefit of this, in my opinion, is that we could have code commonly used on results everywhere written once on the protocol without sacrificing the ability to switch with guarantees. I can see that this suggestion has some rough points so all I will finish by restating the problem that I want to solve. </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">There is code that is fairly common to enum types that have shared characteristics and/or purpose. I would find it useful to have a way to implement shared algorithms in a generic way while retaining core features of enums.</div></div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Fri, Oct 21, 2016 at 11:11 AM, Mike Kasianowicz via swift-evolution <span dir="ltr" class="gmail_msg"><<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">Just from an outside perspective, the class restriction seems to be there as a kludge for technical reasons... but that's neither here nor there.<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">It is not so much to enforce a lack of identity - in the struct case, it would be to enforce copy-by-value semantics. I think the strongest argument I've got is, say, a serialization or caching framework where you want to enforce that something is entirely writeable via memory pointer or copyable. A value-type restriction would get us mostly there, albeit there would still be ways to break the contract. However, as noted in my previous email, I see a lot of possibilities for enums too - in that case the protocol somewhat acts as 'base type' without adding the complexity of a base type.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I listed some of my examples in my previous email - I could elaborate if it helps.<br class="gmail_msg"></div></div><div class="m_-7456997437572773063HOEnZb gmail_msg"><div class="m_-7456997437572773063h5 gmail_msg"><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Fri, Oct 21, 2016 at 9:51 AM, Karl Wagner <span dir="ltr" class="gmail_msg"><<a href="mailto:razielim@gmail.com" class="gmail_msg" target="_blank">razielim@gmail.com</a>></span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_msg"><div id="m_-7456997437572773063m_-4430716572333047373m_-3655154836993588012edo-message" class="gmail_msg"><div class="gmail_msg">IIRC, the reason we have "class" there is for the optimiser, so it can optimise for the protocol being satisfied by a reference-counted type. Classes are semantically unique from values because they have identity, which is also something a protocol might want to codify.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">There may be some optimisation gains by requiring all conformers to be values, but <span class="gmail_msg">I struggle to think of why you might want to codify that a conformer should not have identity.</span></div><div class="gmail_msg"><span class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg">Personally I don't really like this asymmetry in the language either, and would support changes to make these two elements more explicit. For example, a magic "hasIdentity" protocol which is automatically satisfied only by classes, and moving the optimisation guides to usage site (e.g. when declaring a variable of type MyProto, I could declare it of type AnyClass<MyProto> or AnyValue<MyProto> instead, to annotate this specific instance as being refcountable or not, without making such optimisation hints part of the MyProto definition)</div><span class="m_-7456997437572773063m_-4430716572333047373HOEnZb gmail_msg"><font color="#888888" class="gmail_msg"><div class="gmail_msg"><div id="m_-7456997437572773063m_-4430716572333047373m_-3655154836993588012edo-signature" style="font-family:'Helvetica Neue','Helvetica',Helvetica,Arial,sans-serif;font:'-apple-system-body'" class="gmail_msg"></div><br class="gmail_msg"><div id="m_-7456997437572773063m_-4430716572333047373m_-3655154836993588012edo-link" class="gmail_msg"></div></div><div class="gmail_msg">- Karl</div></font></span></div><div id="m_-7456997437572773063m_-4430716572333047373m_-3655154836993588012edo-original" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" style="margin:1ex 0 0 0;border-left:1px #ccc solid;padding-left:0.5ex" class="gmail_msg"><div class="gmail_msg"><div class="m_-7456997437572773063m_-4430716572333047373h5 gmail_msg"><div class="gmail_msg">On Oct 21, 2016 at 8:39 am, <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">Mike Kasianowicz via swift-evolution</a>> wrote:<br class="gmail_msg"><br class="gmail_msg"></div></div></div><div class="gmail_msg"><div class="gmail_msg"><div class="m_-7456997437572773063m_-4430716572333047373h5 gmail_msg"><div dir="ltr" class="gmail_msg">Currently protocols can have the class constraint:<div class="gmail_msg">protocol MyProtocol : class {}<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">It would be (a) intuitive and (b) useful to allow such things as:</div><div class="gmail_msg">protocol Model : struct {} or protocol Event : enum {}</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">These types of restrictions can help prevent accidental anti-patterns or misuse of APIs.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Seems simple and non-controversial... right?</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">[Note: I'd like to see even more heavy-handed protocol restrictions in the future. For example, a protocol describing an enum with a common case, or a struct with no reference members. Great stuff for defensively coding APIs.]</div></div></div></div><span class="gmail_msg">
_______________________________________________
swift-evolution mailing list
<a dir="ltr" href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>
<a dir="ltr" href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a>
</span></div></blockquote></div></div></div></blockquote></div><br class="gmail_msg"></div>
</div></div><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" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
<br class="gmail_msg"></blockquote></div><br class="gmail_msg"></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>