Propose simpler string constant

Isiah Meadows isiahmeadows at gmail.com
Thu Dec 17 11:15:01 UTC 2015


@Alex Those languages have this thing called static types, which enable
many of those optimizations.

On Thu, Dec 17, 2015, 04:09 Alexander Jones <alex at weej.com> wrote:

> 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 <Ron.Buckton at microsoft.com>
> 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:es-discuss-bounces at mozilla.org] On Behalf Of
>> > Brendan Eich
>> > Sent: Wednesday, December 16, 2015 10:04 AM
>> > To: Alican Çubukçuoğlu <alicancubukcuoglu at gmail.com>; es-
>> > discuss at mozilla.org
>> > Subject: Re: Re: Propose simpler string constant
>> >
>> > On Wed, Dec 16, 2015 at 9:41 AM Alican Çubukçuoğlu
>> > <alicancubukcuoglu at gmail.com <mailto:alicancubukcuoglu at gmail.com> >
>> > 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
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151217/ef6073cf/attachment-0001.html>


More information about the es-discuss mailing list