<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 9:48 AM, Kevin Wooten <<a href="mailto:kdubb@me.com" class="">kdubb@me.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 8:42 AM, plx via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">The motivating/most-common case for me is serialization:</div><div class=""><br class=""></div><div class="">coder.encodeInteger(self.enumerationCase.rawValue, forKey: “case")</div><div class="">switch self {</div><div class=""> case let .Foo(data): coder.encodeX(data, forKey: “data”)</div><div class=""> case let .Bar(data): coder.encodeY(data, forKey: “data”)</div><div class="">}</div><div class=""><br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">Solvable now via…</div><div class=""><br class=""></div><div class="">switch self {</div><div class=""> case let .Foo(data):</div><div class=""> coder.encodeInteger(…)</div><div class=""> coder.encodeX(..)</div><div class=""> case let .Bar(data):</div><div class=""> coder.encodeInteger(…)</div><div class=""> coder.encodeY(…)</div><div class="">}</div><div class=""><br class=""></div><div class="">It’s only missing an integer raw value assigned by the compiler.</div></div></div></div></blockquote><div><br class=""></div><div>Well, it’s also missing:</div><div><br class=""></div><div>- a compiler-enforced exhaustiveness check here:</div><div><br class=""></div><div>guard let enumerationCase = EnumerationCase(rawValue: coder.decodeIntegerForKey(“case”)) else { return nil }</div><div>switch enumerationCase {</div><div> case IntegerForFooCase: …</div><div> case IntegerForBazCase: …</div><div> // forgot about Bar! and Quux!</div><div>}</div><div><br class=""></div><div>…along with compiler-enforced “no typo/no-duplicate/no-forget” checks here:</div><div><br class=""></div><div>// in encode:</div><div>case let .Foo(data):</div><div> coder.encodeInteger(1, ..)</div><div> coder.encodeX(…)</div><div>case let .Bar(data):</div><div> coder.encodeInteger(1, ..) // oopsie</div><div> coder.encodeY(…)</div><div class=""><div>case let .Baz(data):</div><div> coder.encodeInteger(3, ..)</div><div> coder.encodeZ(…)</div></div><div><div class=""><div>case let .Quux(data):</div><div> // oopsie! if only i didn’t have to repeat myself!</div><div> coder.encodeW(…)</div></div><div class=""><br class=""></div></div><div><div>// in decode:</div><div>switch caseInteger {</div><div> case 1: // try to decode Bar // oopsie</div><div> case 2: // try to decode Foo // oopsie</div><div> case 4: // try to decode Baz (//oopsie!)</div><div> // oopsie, forgot about Quux</div><div>}</div><div class=""><br class=""></div></div><div>…and once I’m doing this:</div><div><br class=""></div><div>extension Example {</div><div> static let SerializationIntegerForFoo: Int = 1</div><div> static let SerializationIntegerForBar: Int = 2</div><div> // etc.</div><div><br class=""></div><div> var caseSerializationInteger: Int { </div><div> get {</div><div> switch self {</div><div> case .Foo(_): return .SerializationIntegerForFoo // etc.</div><div> }</div><div> }</div><div> }</div><div>}</div><div><br class=""></div><div>…we’re back to the same boilerplate, just written manually and without, e.g., the benefit of exhaustiveness checks in our switch statements.</div><div><br class=""></div><div>Outside serialization, the construct has some miscellaneous handiness, e.g.:</div><div><br class=""></div><div>enum SomeStateMachineStateData<A,B,C> {</div><div> case Initialized</div><div> case StateA(A)</div><div> case StateB(B)</div><div> case StateC(C)</div><div> case MixedAB(A,B)</div><div>}</div><div><br class=""></div><div>// ^ *not* obj-c visible</div><div><br class=""></div><div>@objc</div><div>enum SomeStateMachineState : Int {</div><div> case Initialized</div><div> case StateA</div><div> case StateB</div><div> case StateC</div><div> case MixedAB</div><div>}</div><div><br class=""></div><div>// ^ objc-visible</div><div><br class=""></div><div>…(and similar) which makes it easier to, say, have an obj-c delegate protocol `SomeStateMachineDelegate` that can “follow along” with the associated state machine’s transitions.</div><div><br class=""></div><div>Anyways, this isn’t a request that would make previously-unsolvable problems solvable, it’s merely a request for some compiler assistance reducing certain types of boilerplate, offered up in a discussion of other possible enumeration-related boilerplate reduction (isX(), projectX(), etc.).</div><div><br class=""></div><div>On an importance scale from 1-10 it’s maybe a 3 for me personally, but I’d hate to see e.g. synthesis of `isX()` make it into the language without having at least seen if anyone else is interested on this one as well.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">…etc., and the obvious use of the above when decoding (decode the case, switch on it, decode data).</div><div class=""><br class=""></div><div class="">Once you have it it’s occasionally handy in other contexts, but that’s by far the main motivation.</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 9:35 AM, Kevin Wooten <<a href="mailto:kdubb@me.com" class="">kdubb@me.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I get the gist of what you are requesting and I can see it might me useful but given that<div class=""><br class=""></div><div class="">if case .Foo(_) == ex {</div><div class="">}</div><div class=""><br class=""></div><div class="">Provides comparison, regardless of the # of associated values in .Foo, I’m not sure generating a second enum just to carry a diminished amount of information is worth it.<br class=""><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 8:24 AM, plx via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">FWIW, as long as we’re asking for some compiler assistance generating useful enumeration-related boilerplate, I’d like to request that something along these lines be possible in some version of Swift:</div><div class=""><br class=""></div><div class="">@synthesize_case_enum</div><div class="">enum Example {</div><div class=""><br class=""></div><div class=""> case Foo(X)</div><div class=""> case Bar</div><div class=""> case Baz(Y)</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">…which would then by default expand to something like this:</div><div class=""><br class=""></div><div class="">enum ExampleCase : Int {</div><div class=""> </div><div class=""> case Foo</div><div class=""> case Bar</div><div class=""> case Baz</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">extension Example {</div><div class=""> </div><div class=""> var enumerationCase: ExampleCase {</div><div class=""> get {</div><div class=""> switch self {</div><div class=""> case .Foo(_): return .Foo</div><div class=""> case .Bar(_): return .Bar</div><div class=""> case .Baz(_): return .Baz</div><div class=""> }</div><div class=""> }</div><div class=""> } </div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">…in the default case, but with some customization of the synthesized enumeration-case-enum’s details.</div><div class=""><br class=""></div><div class="">For the remaining proposals:</div><div class=""><br class=""></div><div class="">- `isX()` is nice (and should always `-> Bool`, IMHO)</div><div class="">- `projectX()` is nice and should:</div><div class=""> - *not* be defined for enums w/out associated values</div><div class=""> - `-> T?` for enums w/ a single associated value</div><div class=""> - -> the full tuple, for enums w/ multiple associated values, e.g.:</div><div class=""> - `Foo(A,B)` yields `projectFoo() -> (A,B)?</div><div class=""> - `Event(place: Place, time: Time)` -> (place: Place, time: Time)?</div><div class=""> - (which is essentially the same as for the single-value case, just making it explicit)</div><div class=""><br class=""></div><div class="">…which has the benefit of predictability (and if you need more convenience, replace your tuples with actual classes-or-structs). </div><div class=""><br class=""></div><div class="">Finally, as convenient as the `associatedValue` proposal is down below, it seems better-served by some sort of generalized delegation construct; at a minimum, I don’t think it's that uncommon to have N cases all wrapping the same underlying type, and in such cases working with an `Any?` would feel rather clunky.</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 9, 2015, at 3:00 PM, Andrew Bennett via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">I really like this solution and perhaps you can also go @projectable("empyValue") if the default name is a bad choice. See @obc for similar usage.<span class=""></span><br class=""><br class="">On Thursday, 10 December 2015, Alex Lew via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">Semantically, I believe enums with more than one associated value are actually just enums with one associated value, of tuple type.<div class=""><br class=""></div><div class="">I'm not convinced it would be bad to do magic function generation, but it's worth considering explicit syntax. If we were to use @ compile-time attributes, maybe it could be a word before the case -- like @projectable or @selectable (or some better name)?</div><div class=""><br class=""></div><div class="">enum List<T> {</div><div class=""> @projectable case Empty</div><div class=""> indirect case FirstAndRest(T, List<T>)</div><div class="">}</div><div class=""><br class=""></div><div class="">generates:</div><div class="">myList.isEmpty() -> Bool</div><div class=""><br class=""></div><div class="">Another option: some sort of @reflectable attribute on the enum itself.</div><div class=""><br class=""></div><div class="">@reflectable enum Pet {</div><div class=""> case Cat(name: String, color: String)</div><div class=""> case Dog(name: String, breed: String)</div><div class=""> case Bear(name: String, isHibernating: Bool)</div><div class="">}</div><div class=""><br class=""></div><div class="">And one other option, in a very different direction, that seems weird but maybe has its benefits:</div><div class=""><br class=""></div><div class="">What if we exposed an associatedValue computed property of type Any? (It would be unit type for cases with no associated value.)</div><div class=""><br class=""></div><div class="">You could then do something like this:</div><div class=""><br class=""></div><div class="">enum Contact {</div><div class=""> case Person(String) // name</div><div class=""> case Business(String) // org name</div><div class=""> case FamilyMember(String) // relation name</div><div class=""> case RecentCall(Int) // a contact from caller id, only store the phone number</div><div class=""><br class=""></div><div class=""> func name() -> String {</div><div class=""> return associatedValue as? String ?? "Unknown (\(associatedValue as! Int))"</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">Essentially, it allows you to project out a relatively common associated value (in this case a string) without much boilerplate. It's also just one thing for the compiler to generate, instead of <i class="">n</i>. Not crazy about any of these... just brainstorming. It may also be that a concise switch-like control flow expression eliminates the need for this.</div><div class=""><br class=""></div><div class="">-Alex</div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Wed, Dec 9, 2015 at 11:49 AM, <a href="javascript:_e(%7B%7D,'cvml','thorsten@portableinnovations.de');" target="_blank" class="">thorsten@portableinnovations.de</a> <span dir="ltr" class=""><<a href="javascript:_e(%7B%7D,'cvml','thorsten@portableinnovations.de');" target="_blank" class="">thorsten@portableinnovations.de</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=""></div>
<div class="">
<span style="background-color:rgba(255,255,255,0)" class="">I would prefer if no "magic" methods would be generated automatically, but only when marked with @derivestandardmethods (fill in better name here).</span>
</div>
<div class="">
<span style="background-color:rgba(255,255,255,0)" class=""><br class=""></span>
</div>
<div class="">
<span style="background-color:rgba(255,255,255,0)" class="">As to naming I like the proposal #1 by Alex.</span>
</div>
<div class="">
<span style="background-color:rgba(255,255,255,0)" class=""><br class=""></span>
</div>
<div class="">
<span style="background-color:rgba(255,255,255,0)" class="">What about enums with more than one associated value?</span><span class=""><font color="#888888" class="">
</font></span></div><span class=""><font color="#888888" class="">
<div class="">
<span style="background-color:rgba(255,255,255,0)" class=""><br class=""></span>
</div>
<div class="">
<span style="background-color:rgba(255,255,255,0)" class="">-Thorsten</span>
</div></font></span><div class=""><div class="">
<div class="">
<br class="">Am 09.12.2015 um 07:29 schrieb Alex Lew via swift-evolution <
<a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank" class="">swift-evolution@swift.org</a>>:
<br class="">
<br class="">
</div>
<blockquote type="cite" class="">
<div class="">
<div dir="ltr" class="">
Thanks, Chris, for all the time you're putting into responding to these proposals (and the kindness with which you're responding!). I really like that solution.
<div class="">
<br class="">
<div class="">
<div class="">
Brainstorming some names for the auto-generated functions:
</div>
<div class="">
<br class="">
</div>
<div class="">
1. If a case has no associated values, isX() -> Bool is generated, where X is the case name.
</div>
<div class="">
If a case has an associated value of type T, asX() -> T? is generated, where X is the case name.
</div>
</div>
<div class="">
This mirrors is/as? operators, which return Bool / Optional respectively.
</div>
<div class="">
2. projectX() -> Bool / projectX() -> T?
</div>
<div class="">
3. isX() -> Bool / xValue() -> T?
</div>
<div class="">
<br class="">
</div>
<div class="">
Another option (probably the wrong option, but it's worth putting out there) is that instead of returning Bool in the no-associated-value case, we return ()?. This would make me feel better about using the same naming convention (asX(), projectX(), xValue(), etc.) for each case, and would allow for != nil checks on all cases. But it would probably be a little confusing for newcomers to the language.
</div>
<div class="">
<br class="">
</div>
<div class="">
<div class="">
One (potentially misguided) question. I noticed in proposal 0002 (on removing function currying) that there are "plans to move away from the arguments-are-a-single-tuple model" in the near future. Would this also affect associated values of enums? That is, might
</div>
<div class="">
<br class="">
</div>
<div class="">
case Dog(name: String, age: Int, breed: String)
</div>
<div class="">
<br class="">
</div>
<div class="">
one day not have the semantics of a single associated value of type (name: String, age: Int, breed: String)? Or is the de-ML-ification planned only for function arguments?
</div>
</div>
<div class="">
<br class="">
</div>
<div class="">
-Alex
</div>
</div>
</div>
<div class="gmail_extra">
<br class="">
<div class="gmail_quote">
On Wed, Dec 9, 2015 at 12:45 AM, Chris Lattner
<span dir="ltr" class=""><<a href="javascript:_e(%7B%7D,'cvml','clattner@apple.com');" target="_blank" class="">clattner@apple.com</a>></span> wrote:
<br class="">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br class=""> > On Dec 7, 2015, at 8:05 PM, Alex Lew via swift-evolution <<a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank" class="">swift-evolution@swift.org</a>> wrote:<br class=""> ><br class=""> > Hi all,<br class=""> ><br class=""> > Curious to hear thoughts on allowing non-binding pattern matches to be used as boolean values outside of an if, guard, for...in, while, switch, etc. Something like:<br class=""> ><br class=""> > enum List<T> {<br class=""> > case Empty<br class=""> > indirect case Link(T, List<T>)<br class=""> ><br class=""> > func isEmpty() -> Bool {<br class=""> > return case .Empty = self<br class=""> > }<br class=""> > }<br class=""> <br class=""> </span>I agree with you that this is a problem that we should solve, but I think it could be solved in a different way. Imagine if:
<br class="">
<br class=""> enum Foo {
<br class=""> case X(a : Float), Y, Z(a : Int)
<br class=""> }
<br class="">
<br class=""> automatically synthesized these members (the exact names are just a strawman proposal, not serious :-)
<br class="">
<br class=""> extension Foo {
<br class=""> func isX() -> Float? {…}
<br class=""> func isY() -> Bool {…}
<br class=""> func isZ() -> Int? {…}
<br class=""> }
<br class="">
<br class=""> This would tie into all of the mechanics we have for dealing with optionals, e.g. if/let and ??
<br class="">
<span class=""><font color="#888888" class=""><br class=""> -Chris</font></span>
</blockquote>
</div>
<br class="">
</div>
</div>
</blockquote>
</div></div><div class=""><div class=""><blockquote type="cite" class="">
<div class="">
<span class="">_______________________________________________</span>
<br class="">
<span class="">swift-evolution mailing list</span>
<br class="">
<span class=""><a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank" class="">swift-evolution@swift.org</a></span>
<br class="">
<span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span>
<br class="">
</div>
</blockquote>
<div style="margin-top:10px;font-size:12px;font-family:Helvetica,Arial;color:#999" class="">
Untracked with
<a style="color:#999" href="https://trackbuster.com/?sig" target="_blank" class="">Trackbuster</a>
</div></div></div></blockquote></div><br class=""></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=pQw7h83fWt3LLbgkfL4TSUL0weaZnVFZxDe5GShw4uQDHC8-2Bb5Mm2h8Fr1ebZpHulz7MNVAtz7ytkHH1B6sCvMqhblCu-2FtishBvo8NtHZrP4U-2FJqTGbBAim-2F7GB2sw3hKh4p9q23gPE9ZxSpdJqNiz3QG1-2FWGakSUpmlk6PWXscxYX6MM3Kn1fBzGnEezQ-2FW1GrPKNIWbn1SVPe-2BKsgEwROSylxAZnUF606nSYeitPg-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important" class="">
</blockquote>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=9EwXyNl81W9TT3yZ17PL28-2Be7Ks-2FXLjqa0dZcsddi5Z3FU3UaQ85-2BE-2FTY7KwrdfHhLrKCpmYZkR5jNmoAqU48ODL8yLLsgl9mtYD-2BNkmFpTKUMDSfFkWITPc03ME864eqxcpDAObun4ki-2B5Hoj3q10b-2BtWgN8JBCrknWtRSqwcZA-2F138zJLTn4lk3MOd2b1OBQpiy8e0Q8to8CZvOsApVLkOQyZWvr0Z-2FcHDXfaVWlI-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class="">
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=1Ry8ov4zuU66O51YNcjYWb8a53-2BUz0PFweQpx-2Fs9koACaNnwcLfxYiCUybqXWtB2U4apzklK6XSGc46S1D7vsrdYh-2Fx4XzhD7WavisoZP8JNdozNmzUb2EW-2Fujl9-2Fd7PZp18jX1b-2F1Yga9ksPxLfICEOy4HSrhL-2BcFiirjJx3oA4W5ZRNFSQAj2PA8EKacZsVPbQcO9bID-2Fd29lNo9cpXQ-3D-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></div></div></blockquote></div><br class="">
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=1Ry8ov4zuU66O51YNcjYWeLZ2jEHk8vhiClUS-2BejOUQ3O4TBAxnwPjFe7vHfog08dQ0LhN0Rk3PvwAfOpbh6vbLDv972GleJLx7qulA8-2FfTKXDHPaJIOg-2BgkflE4w7uxKUZ1KvhseE4N2W58PLNBArle68WgbPlXX0onnfn3XKJzbnv0KjnmSjUpY8a7tm1T0wZZCJYxsipo64NhpYkZ9Q-3D-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>