I think we can do better than to follow C#'s lead, if that's the case. I don't see what the point in `Color.Red - Color.Green` is. Languages like Rust, Swift, OCaml are providing full Algebraic Data Types that approach this whole domain from a better level. Also, I don't like the idea of overloading enum for both sets of combineable flags and sets of distinct values - that seems like a lack of a good abstraction. Look to Qt for IMO a pretty good one: http://doc.qt.io/qt-4.8/qflags.html
Alex On Wednesday, 16 December 2015, Ron Buckton <[email protected]> wrote: > In C#, an enum is a declaration that defines a distinct type consisting of > a set of named constant values of that type. The distinct type of the enum > has an underlying numeric base type, such as byte, int, long, etc. By > default, each constant value is assigned an incrementing integer value > starting from 0, although this sequence can be interrupted by assigning an > explicit integer value: > > ```cs > enum Colors { Red, Green, Blue } > Colors.Red // 0 > Colors.Green // 1 > Colors.Blue // 2 > > enum Days: byte { Sat = 1, Sun, Mon, Tue, Wed, Thu, Fri } > Days.Sat // 1 > Days.Sun // 2 > ``` > > C# enum values can be used with many standard numeric operations, and are > often heavily used with bitwise operators. A C# enum value is a constant > value, and is internally treated as a numeric literal by the compiler. In > any C# enum declaration, only constant numeric values can be explicitly > assigned to an enum member, although constant reduction is permitted: > > ```cs > enum UriComponents { > Scheme = 0x1, > UserInfo = 0x2, > Host = 0x4, > Port = 0x8, > Path = 0x10, > Query = 0x20, > Fragment = 0x40, > AbsoluteUri = Scheme | UserInfo | Host | Port | Path | Query | Fragment > } > ``` > > Although C# enum values are converted to numeric literals by the compiler, > their type information is preserved. This allows for an enum type to have > different behavior from a literal numeric type. One example of this > behavior is how ToString is handled on an enum value: > > ```cs > enum Numbers { Zero, One, Two } > (int)Numers.Zero // 0 > Numbers.Zero.ToString() // Zero > ``` > > The enum type itself has a number of static methods to make it easier to > program against, including: GetName, GetNames, GetUnderlyingType, > IsDefined, Parse, and ToObject. Instance members of an enum type include > HasFlag and CompareTo. > > In TypeScript we treat an enum declaration in a fashion similar to a C# > enum, with respect to how we handle incremental integer values and > explicitly assigned values. We effectively emit an enum as an object > literal: > > ```ts > // TypeScript > enum Colors { Red, Green, Blue } > > Colors.Red // 0 > > // JavaScript > var Colors; > (function (Colors) { > Colors[Colors[0] = "Red"] = 0; > Colors[Colors[1] = "Green"] = 1; > Colors[Colors[2] = "Blue"] = 2; > })(Colors || (Colors = {})); > > Colors.Red // 0 > ``` > > In this way, you can use `Colors.Red` to get the value 0, and `Colors[0]` > to get the value "Red". As a performance optimization we also have what we > call "const enums". A const enum can be completely erased by the compiler: > > ```ts > // TypeScript > const enum Colors { Red, Green, Blue } > > Colors.Red // 0 > > // JavaScript > 0 /*Colors.Red*/ // 0 > ``` > > I think a general proposal for ES enums would be a combination of the > above approaches, with some additions: > > * An enum can be a declaration or an expression. > * The body of an enum consists of a new lexical scope. > * Enum members are standard JavaScript identifiers. > * Enum members are automatically assigned an incrementing integer value, > starting at zero. > * Enum members can be explicitly assigned to an integer value, or another > enum value. > * Within the body of an enum, Enum members can be accessed in the > initializer without qualification. > * Within the body of an enum, Enum members are lexically declared names > and cannot be accessed before they are defined (TDZ). > * An enum declaration can be called as a function to convert a string or > numeric value into the enum value, making enum types distinct from numbers > and from each other. [1] > * The result of `typeof` on an enum value is `enum`. > * Enum values support (at least) the following operators, returning an > enum value of the same type: + (unary), - (unary), ~, + (binary), - > (binary), | (binary), & (binary), ^ (binary). > * Any binary operation between two enums of different types is a > TypeError. [1] > * Any binary operation between an enum and a number first converts the > number to the enum type. If the number is not an integer it is a TypeError. > * Any binary operation between an enum and a string first converts the > enum into the string value for that enum based on the enum member's > JavaScript identifier (if present), or the string representation of its > integer numeric value. [2] > * Calling Number() with an enum value as its first argument returns its > underlying number value. > * Calling String() with an enum value as its first argument returns the > string value for the enum member that defines the number (if present), or > the string representation of its integer numeric value. [2] > * Calling the valueOf() instance method on an enum value has the same > effect as Number() above. > * Calling the toString() instance method on an enum value has the same > effect as String() above. [2] > * Two enum members on the same enum or differing enum types with the same > underlying integer value are equivalent (==) but not strictly/reference > equivalent (===). [1] > > I think these rules could satisfy both anyone who needs enum values to be > numeric (to support bitwise operations, bitmasks, ordinal indices, etc.) > and those that would like enum values to be unique in a fashion similar to > using Symbol(). > > [1] We have noticed in TypeScript some issues with Symbol-like equivalence > with enums if you have two versions of the same module in NodeJS due to > specific version dependencies, where you could have a.Color.Red !== > b.Color.Red if *a* and *b* are different versions of the same module. > Generally I think having enum values just really be numbers and not > differing between == and === is less of a footgun. > > [2] If enum values of different types should be === to each other, you > should not be able to get a different result when you call .ToString(). In > that case, we could add a static `getName` method to the enum type to get > the string value for an enum. > > Ron > > > -----Original Message----- > > From: es-discuss [mailto:[email protected] <javascript:;>] > On Behalf Of > > Brendan Eich > > Sent: Wednesday, December 16, 2015 10:04 AM > > To: Alican Çubukçuoğlu <[email protected] <javascript:;>>; es- > > [email protected] <javascript:;> > > Subject: Re: Re: Propose simpler string constant > > > > On Wed, Dec 16, 2015 at 9:41 AM Alican Çubukçuoğlu > > <[email protected] <javascript:;> <mailto: > [email protected] <javascript:;>> > > > wrote: > > > > > > How are enums declared? > > ```javascript > > let myVar = 13; > > enum myEnum = {Red, Green, Blue}; > > > > > > No `=` between name and `{`. > > > > Enumerator scope is a good question. Clearly we do not want global scope. > > Rather, as a declaration immedicately contained by a block or top > > level, we want lexical scope for the enum name -- and (I think) for the > enumerators' > > individual names. > > > > What about enumerator name scope for enum in class, without `static`? > > I'm not sure, but precedent says that the enumerator names define > > prototype properties. > > > > Expression as well as declaration `enum` form follows class and > > function precedent. Expression form requires a reserved identifier > > (not sym or sum or whatever), which `enum` has been forever, fortunately. > > > > I agree symbol values by default, with ` = 0` or some other number > > than > > 0 after the first enumerator name, looks confusing. Recall the first > > use-case in the o.p. was (implicit, should rather be explicit) > > reflection on the string value that spells the enumerator name. > > > > /be > _______________________________________________ > es-discuss mailing list > [email protected] <javascript:;> > https://mail.mozilla.org/listinfo/es-discuss >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

