proposal-enum
proposal-enum copied to clipboard
Motivation / problem being solved?
The README doesn't really explain what problem this proposal is setting out to solve, which makes it hard to evaluate.
I have communicated with rbuckton. I'll revisit the materials see if I can cover the support of shared structs (which rbuckton's version intended to support). After revisiting the materials I'll update the documentation.
@Jack-Works this is the same reply you sent to https://github.com/Jack-Works/proposal-enum/issues/22
I have updated the README to include the motivation and current status.
"Provide enum (Enumerated type) in JavaScript." isn't really a motivation, it's just what the proposal is. The motivation should explain why it's useful to add - for example, what kinds of things would become easier or clearer to write with this feature.
I wanted to echo here that we don't have an established motivation for this. The motivation should make it clear why (as bakkot described) this needs to be added into the language, and preferably answering also: why now.
About the motivation: I can't express my thoughts accurately, but I feel we're missing this feature for a long time. Many languages have them and they're useful. I think the motivation of rbuckton's version also applies. https://github.com/rbuckton/proposal-enum#motivations
About why now: I'm not hurrying to push this forward before we fully explored the problem. I want to push this to stage 1 just because I want to gather people who are interested in this work and have formal/regular discussions about this topic.
Motivation that other languages have enums is lackluster. We need a motivation why ECMAScript should have an enum and more precisely, motivations for someone to use enums instead of existing language features.
Value auto-increment is a valid feature that's missing in core language currently. It's rather simple to implement in code though for customEnum = autoIncrement(['First', 'Second', ['Fifth', 5], 'Sixth'])
.
Another possiblity is the static analysis, but I feel like it's already out of scope of ECMAScript. I think it's futile to add a feature and make sure it doesn't have cracks when the whole original vessel has enormous holes due to the language being dynamic. There are good external tools for static analysis already and they are widely recommended - are there any issues with existing code where enums specifically would make the tools provide better analysis?
Abstract Data Types could fill the role of a winner feature, but I wish to see more convincing arguments why "Plain Enums" as a separate proposal, by it's own merits alone, deserves the needed support.
I think the big selling point of enum
is obviousness of intent. Consider a similar feature which strictly speaking offers nothing the language didn't already provide, private fields, those could be implemented entirely with WeakMap
, however using:
const state = new WeakMap();
class Resource {
constructor() {
state.set(this, "idle");
}
async load() {
if (!state.has(this)) {
throw new TypeError(`value does have not private state`);
}
state.set(this, "loading");
const resource = await getTheResourceSomehow();
state.set(this, "ready");
return resource;
}
}
feels considerably less clear than doing:
class Resource {
#state = "idle";
async load() {
this.#state = "loading";
const resource = await getTheResourceSomehow();
this.#state = "ready";
return resource;
}
}
Enums are pretty similar in this regard, they give intent that something is indeed an enumeration rather than some other kind of object, i.e. compare:
// You could extract this stuff to a library with methods, but this adds more
// indirection and requires people to understand your specify "enum" semantics
// for such a definition
const storageKind = new Map([
["number", 0],
["bigint", 1],
["array", 2],
]);
const storageKindInverted = new Map(
Array.from(storageKind.values()).map(([key, value]) => [value, key]),
);
/**
* @param {ArrayBuffer} buffer
* @returns {any}
*/
function loadFromBuffer(buffer) {
const view = new DataView(buffer);
const kind = view.getInt32(0);
const kindName = storageKindInverted.get(kind);
if (kindName === "number") {
// load a number
}
// etc
}
/**
* @param {any} value
* @returns {ArrayBuffer}
*/
function storeInBuffer(value) {
if (typeof value === "number") {
const view = new DataView(new ArrayBuffer(12));
const kind = storageKind.get("number");
view.setI32(0, kind);
view.setFloat64(4, value);
return view.buffer;
}
// etc
}
Compared to:
enum StorageKind {
number = 0,
bigint = 1,
array = 2,
}
/**
* @param {ArrayBuffer} buffer
* @returns {any}
*/
function loadFromBuffer(buffer) {
const view = new DataView(buffer);
const kind = view.getInt32(0);
const kindName = storageKind.nameOf(kind);
if (kindName === "number") {
// load a number
}
// etc
}
/**
* @param {any} value
* @returns {ArrayBuffer}
*/
function storeInBuffer(value) {
if (typeof value === "number") {
const view = new DataView(new ArrayBuffer(12));
const kind = storageKind.number;
view.setI32(0, kind);
view.setFloat64(4, value);
return view.buffer;
}
// etc
}
While the difference may not be huge, the intent is a lot clearer. (Again this is very similar to private fields).
hope I answered those questions well https://github.com/Jack-Works/proposal-enum/pull/30