<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><div><div style="font-family: Calibri,sans-serif; font-size: 11pt;">I think I should start writing that proposal for enum case names now.<br><br>L</div></div><div dir="ltr"><hr><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">From: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:swift-evolution@swift.org">Vladimir.S via swift-evolution</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Sent: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;">01/06/2016 07:02 PM</span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">To: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:allevato@google.com">Tony Allevato</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Cc: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:swift-evolution@swift.org">swift-evolution</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Subject: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;">Re: [swift-evolution] Ad hoc enums / options</span><br><br></div> > in other words, we could consider allowing this:<br> > func foo(bar: (.fit | .fill)) {<br> > baz(bar: bar)<br> > }<br> > func baz(bar: (.fit | .fill | .florp) { ... }<br> ><br> > In other words, an ad hoc enum T can be used wherever an ad hoc enum U is<br> > expected if T ⊆ U.<br><br>Can't agree with this. Just because the same analogue with tuples : <br>differently defined tuples are different types. Tuples with different order <br>of types in declaration - are different types. So I expect here instance of <br>(.fit | .fill) `bar` is not of the same type as (.fit | .fill | .florp)<br><br>But +1 to be able to 'convert' instance of (.fit | .fill) to instance of <br>(.fit | .fill | .florp). For example(if we'll have init(caseName) and <br>.caseName for enums):<br><br>func foo(bar: (.fit | .fill)) {<br> let bazbar = (.fit | .fill | .florp).init(caseName: bar.caseName)<br> baz(bar: bazbar)<br>}<br>func baz(bar: (.fit | .fill | .florp) { ... }<br><br><br><br>On 02.06.2016 0:38, Tony Allevato wrote:<br>> I find myself agreeing with the idea that ad hoc enums are to enums as<br>> structs are to tuples. Based on that analogy, why should an ad hoc enum<br>> *need* a name (autogenerated or otherwise) any more than a tuple needs a<br>> name? Would those who dislike ad hoc enums argue that this also shouldn't<br>> be allowed:<br>><br>> func foo(bar: (x: Int, y: Int)) {}<br>> let t: (x: Int, y: Int) = (x: 5, y: 5)<br>><br>> If someone writes `(.fit | .fill)` (or whatever the hypothetical syntax<br>> might be), that should just *be* the type the same way that `(x: Int, y:<br>> Int)` is a type without a name, and that type can be used in argument<br>> lists, variables, or whatever. There shouldn't be any worry about<br>> declarations across multiple functions colliding or being incompatible any<br>> more than we would worry about two functions declaring arguments of type<br>> `(x: Int, y: Int)` would collide or be incompatible.<br>><br>> One side of ad hoc enums that I'd like to see explored is that, by being<br>> unnamed, they're basically anonymous finite sets and we could apply<br>> well-defined subset relationships to them: in other words, we could<br>> consider allowing this:<br>><br>> func foo(bar: (.fit | .fill)) {<br>> baz(bar: bar)<br>> }<br>> func baz(bar: (.fit | .fill | .florp) { ... }<br>><br>> In other words, an ad hoc enum T can be used wherever an ad hoc enum U is<br>> expected if T ⊆ U.<br>><br>><br>> On Wed, Jun 1, 2016 at 1:43 PM L. Mihalkovic via swift-evolution<br>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:<br>><br>><br>><br>> > On Jun 1, 2016, at 6:51 PM, Vladimir.S <svabox@gmail.com<br>> <mailto:svabox@gmail.com>> wrote:<br>> ><br>> > Yes, I also can support the idea of autogenerated type name (like<br>> Enum_fit_OR_fill) as long as it allows to do all the things we are<br>> discussing here: declare (.fit|.fill) in function, use .fit on calling<br>> side, use (.fit|.fill) to declare temporary variable of type compatible<br>> with such function parameter etc.<br>> ><br>><br>> It all works because the compiler is just being a thoughless scribe<br>> that just writes the standard enum we don't bother to write ourselves.<br>> Because the heuristic is simple and straightforward then it is<br>> predictible. The enum can be used with its long name be ause it is a<br>> real enum. And writing the short form of it also works because the<br>> compiler knowns uniquely what the long name is everytime it runs into<br>> the short name.<br>><br>><br>> > But how do you suggest to define a type of such function in<br>> `typealias` for example? i.e. for func my(option: (.fit|.fill) {..}<br>> ><br>> > typealias MyFunc = ((.fit|.fill)) -> ()<br>> > or as<br>> ><br>> > typealias MyFunc = (Enum_fit_OR_fill) -> ()<br>> ><br>><br>> Ideally there is no difference whatsoever, there is a single enum, it<br>> is produced at the module level, and it has the long form name.<br>><br>> There can be rules that would prevent us from doing that with<br>> externally visible APIs, if the core team fuges that we should take the<br>> time to write our enums manually and cleanly to make them visible to<br>> the world, but it is not a necessary rule.<br>><br>><br>> ><br>> > But I still can't support the idea of limiting the usage of such<br>> enums - i.e. "To deal with milti site definition, the compiler would<br>> simply flag a error/warning, or be silent in the presence of a new<br>> annotation:". I really think we need then introduce the same rule for<br>> tuples - so no one can use the same tuple declaration in function -<br>> they then should declare separate struct type or use @something for<br>> such functions. Nobody wants such rule for tuples.<br>> ><br>><br>> Multi site thing is not a limitation... Is is a proposed rule to say<br>> that we are able to be lazy twice without being penalized. Yhe compiler<br>> does not like when we define the same thing twice, and thse short form<br>> amount to doing what he does not let us do. But because this is about<br>> concise and lazy, then the compiler can let us get away with it if we<br>> use an annotation that lets it know that "it is not a mistake.. I<br>> really dont want to write that enum myself, even though I am using the<br>> same abbreviation twice". Otherwise, the compiler would let us know<br>> that the second time could be a mistake because there is already<br>> something with the same name...<br>><br>> But again this is a separate idea from the core notion of a syntax<br>> sugaring for writing real enums the lazy (clever) way<br>><br>> >> On 01.06.2016 19:04, L. Mihalkovic wrote:<br>> >> The only problem with this proposal is to consider them ad-hoc<br>> enums... If we view them as having nothing ad-hoc about them and the<br>> thing to be a simple sugaring exercise, then I think all the opositions<br>> on grounds of breaking the language disapear. It still does not mean it<br>> should be done if the core team does not like the idea of encouraging<br>> laziness, or simply do not like what it makes them look like. No matter<br>> what, this type of sugaring exercise has been clearly stated as out of<br>> scope for 3.0<br>> >><br>> >>>> On Jun 1, 2016, at 2:38 PM, Vladimir.S via swift-evolution<br>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:<br>> >>>><br>> >>>> On 01.06.2016 11:00, Austin Zheng wrote:<br>> >>>> Tuples are a structural type, they are described entirely by the fact<br>> >>>> that they are a tuple, plus their contained types.<br>> >>>><br>> >>>> Enum cases are not individual types; that precedent exists nowhere in<br>> >>>> Swift. You can't (yet) build a structural type out of something that<br>> >>>> isn't a type. The fact that you had to propose something like<br>> >>>> "AdhocEnumFitFill_2383748" as an autogenerated name for the type<br>> >>>> demonstrates the proposal's weaknesses: a tuple is an ad-hoc type that<br>> >>>> describes itself, while an anonymous enum isn't.<br>> >>><br>> >>> Yes, I understand the point about the type of such adhoc enum.<br>> >>> The only workaround I can see in this case(if we'd really want to<br>> have it in language) if adhoc enum type will be `(.Fit|.Fill)` i.e.<br>> textual representation if the declared type. As I understand this also<br>> could not be a solution.. I.e. for example<br>> `(Int,String,(.Fit|.Fill))->String`<br>> >>><br>> >>> From other point of view, adding such type to typesystem will add<br>> some consistence : you can create a function that don't need definition<br>> of separate structure type(tuple will be used) and don't need separate<br>> enum type(ad-hoc enum will be used). I.e. all data the function needs<br>> to process could be described in function definition. Today we need to<br>> use ugly Bool flags in case we want to achieve the same target.<br>> >>><br>> >>>><br>> >>>> Now if enum cases were equivalent if they had the same name (like how<br>> >>>> "Int" means the same thing no matter what tuple or generic type it is<br>> >>>> used in), we'd have a good foundation for a self-describing structural<br>> >>>> type. But this isn't how the existing named enum types work. Why would<br>> >>>> it be a good idea to make anonymous enum cases interchangeable by<br>> name?<br>> >>>> Properties on different types aren't interchangeable, even if they<br>> have<br>> >>>> the same type. In fact, no type member that I am aware of is<br>> >>>> interchangeable solely on the basis of name. An<br>> "ArtistAction.Draw" and<br>> >>>> "CowboyAction.Draw" might have the same name, but they mean completely<br>> >>>> different things.<br>> >>><br>> >>> I don't think they should be 'interchangeable by name', but just<br>> like tuples if you defined adhoc enum with exactly the same cases as<br>> ad-hoc enum in function parameters - then they are of the same type.<br>> >>><br>> >>> I.e. :<br>> >>><br>> >>> func foo(option: (.fit|.fill)) {..}<br>> >>><br>> >>> foo(.fit) // .fit is of type (.fit|.fill) from definition<br>> >>><br>> >>> let e : (.fit|.fill) = .fit<br>> >>> foo(e) // e is of (.fit|.fill) type, equal to definition<br>> >>><br>> >>> but<br>> >>><br>> >>> func foo2(option: (.fit|.fill|.other)) {..}<br>> >>><br>> >>> foo2(.fit) // ok, here .fit is of (.fit|.fill|.other) type<br>> >>> foo2(e) --> Error, e is not of type (.fit|.fill|.other)<br>> >>><br>> >>>><br>> >>>> Finally, I have to ask: if you are updating your anonymous enum in<br>> >>>> multiple places, how much effort have you actually saved over a<br>> one-line<br>> >>>> enum definition? In fact, tuples are a great example of this: best<br>> >>>> practices usually state that they are good for ad-hoc destructuring,<br>> >>>> such as retrieving multiple return values from a function or pattern<br>> >>>> matching across several values at once, but structs are better<br>> used for<br>> >>>> almost everything else, since they carry semantic meaning that tuples<br>> >>>> don't.<br>> >>>><br>> >>><br>> >>> Just the same pros and cons for ad-hoc enums vs enum declaration as<br>> for tuples vs struct declaration. Yes can use it with care and you can<br>> use it in wrong way.<br>> >>><br>> >>> Btw, I feel like this could be very handy to return adhoc enum:<br>> >>><br>> >>> func something() -> (.one|.two|.three) {...}<br>> >>><br>> >>>> I hope that clarifies my thoughts on the matter.<br>> >>>><br>> >>>> Best, Austin<br>> >>>><br>> >>>><br>> >>>>> On Jun 1, 2016, at 12:36 AM, Vladimir.S <svabox@gmail.com<br>> <mailto:svabox@gmail.com>> wrote:<br>> >>>>><br>> >>>>> On 01.06.2016 9:55, Austin Zheng via swift-evolution wrote:<br>> >>>>>> Maybe it's overkill. My personal opinion is that breaking the<br>> >>>>>> symmetry of the language like this (are there any other types of<br>> >>>>>> function arguments that cannot be passed as either variable values<br>> >>>>>> or literals?) is too much a price to pay. Your library thinks it's<br>> >>>>>> being clever and vends its functions as taking anonymous enum flags,<br>> >>>>>> and now there are a bunch of things I can't do with those functions<br>> >>>>>> anymore.<br>> >>>>>><br>> >>>>>> A regular enum can be declared in one line anyways:<br>> >>>>>><br>> >>>>>> enum ScaleCropMode { case Fit, Fill }<br>> >>>>><br>> >>>>> Why do we have tuples? Struct could be defined by one line `struct<br>> >>>>> SomeValue { var x = 0, y = 0 }` ;-) I.e. from my point of view<br>> >>>>> developer should decide what he/she wants to use: ad-hoc enum or<br>> >>>>> defined enum type *exactly* as now he/she can decide to use the same<br>> >>>>> tuples in multiply functions instead of one defined struct type.<br>> >>>>><br>> >>>>> I replied regarding the variable on other message. (In short: I think<br>> >>>>> of the same principle as for tuples: you can declare variable `let e:<br>> >>>>> (.fill | .fit) = .fill` and use it)<br>> >>>>><br>> >>>>>><br>> >>>>>> Austin<br>> >>>>>><br>> >>>>>>> On May 31, 2016, at 11:44 PM, Charles Constant<br>> >>>>>>> <charles@charlesism.com <mailto:charles@charlesism.com><br>> <mailto:charles@charlesism.com <mailto:charles@charlesism.com>>> wrote:<br>> >>>>>>><br>> >>>>>>>> It breaks the ability to pass in a variable containing the<br>> >>>>>>>> desired<br>> >>>>>>> value, rather than the literal value itself.<br>> >>>>>>><br>> >>>>>>> Maybe that's appropriate? If the caller is not passing in a<br>> >>>>>>> hardcoded enum case, then that enum is probably general enough<br>> >>>>>>> that it warrants a normal enum. But there are also situations<br>> >>>>>>> where the same function is called from several files in the same<br>> >>>>>>> code-base with different flags. Those are situations where it<br>> >>>>>>> feels like overkill to clutter up my codebase with separate enums,<br>> >>>>>>> only used by a single function.<br>> >>>>>>><br>> >>>>>>><br>> >>>>>>><br>> >>>>>>><br>> >>>>>>><br>> >>>>>>> On Tue, May 31, 2016 at 9:24 PM, Austin Zheng via swift-evolution<br>> >>>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org><br>> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>><br>> >>>>>>> wrote:<br>> >>>>>>><br>> >>>>>>> I admire the desire of this proposal to increase the readability<br>> >>>>>>> of code. I'm -1 to the proposal itself, though:<br>> >>>>>>><br>> >>>>>>> - It breaks the ability to pass in a variable containing the<br>> >>>>>>> desired value, rather than the literal value itself. (Unless you<br>> >>>>>>> actually want a not-so-anonymous enum type whose definition<br>> >>>>>>> happens to live in a function signature rather than somewhere<br>> >>>>>>> you'd usually expect a type definition to live.) - It breaks the<br>> >>>>>>> ability to store a reference to the function in a variable of<br>> >>>>>>> function type (ditto). - Almost every time I've wanted to use one<br>> >>>>>>> of these "anonymous enums" in my code, I've ended up needing to<br>> >>>>>>> use that same enum elsewhere. In my experience, 'lightweight<br>> >>>>>>> enums' don't end up saving much time compared to a full-fledged<br>> >>>>>>> one.<br>> >>>>>>><br>> >>>>>>> Like Brent said, I have to say no to any proposal that tries to<br>> >>>>>>> make enums synonyms for numerical values. What happens if you<br>> >>>>>>> rearrange your anonymous enum cases between library versions? Do<br>> >>>>>>> you somehow store an opaque case-to-UInt8 table somewhere for<br>> >>>>>>> every anonymous enum you define for resilience? What happens when<br>> >>>>>>> people start bringing back terrible C patterns, like doing<br>> >>>>>>> arithmetic or bitwise ops on the underlying case values? At least<br>> >>>>>>> you have to try pretty hard as it is to abuse Swift's enums.<br>> >>>>>>><br>> >>>>>>> Austin<br>> >>>>>>><br>> >>>>>>> On Tue, May 31, 2016 at 8:25 PM, Brent Royal-Gordon via<br>> <br><div>[The entire original message is not included.]</div></body></html>