Propose simpler string constant

Alexander Jones alex at weej.com
Fri Dec 18 10:28:29 UTC 2015


What optimizations?

On Thursday, 17 December 2015, Isiah Meadows <isiahmeadows at gmail.com> wrote:

> @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
> <javascript:_e(%7B%7D,'cvml','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
>> <javascript:_e(%7B%7D,'cvml','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
>> <javascript:_e(%7B%7D,'cvml','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/20151218/9765f398/attachment.html>


More information about the es-discuss mailing list