The goal is to implement a form of pattern matching that works well in the existing dynamic environment of ECMAScript.
The goal is to find a way to do efficient pattern matching such as using an object tag. JS VMs already have a field for this that is used to tag various kinds of built-in objects.
This tag could be extended to also include a user space range.
The object model is that each constructor function has an internal [[Tag]]
slot. Which can be a small number within some range (e.g. 0-255). Each object created using [[Construct]]
on this constructor gets this [[Tag]]
on its internal [[Tag]]
slot.
A reflective API e.g. Tag.of(obj)
extracts the tag. This can then be used in a switch statement. The Tag.of
numbers are their respective number. The Tag.of
on null
is zero.
const MyEnum = {
None: 0,
Foo: 1,
Bar: 2
};
class Foo {
}
Tag.set(Foo, MyEnum.Foo);
class Bar {
}
Tag.set(Bar, MyEnum.Bar);
let obj = new Bar();
let type;
switch (tagof(obj)) {
case MyEnum.None:
type = 'None';
break;
case MyEnum.Foo:
type = 'Foo';
break;
case MyEnum.Bar:
type = 'Bar';
break;
}
console.log('This is a ', type);
enum MyEnum {
None: null;
class Foo {
}
class Bar {
}
};
let obj = new MyEnum.Bar();
let type = switch(obj) {
| MyEnum.None: 'None';
| MyEnum.Foo: 'Foo';
| MyEnum.Bar: 'Bar';
};
console.log('This is a ', type);
ECMAScript uses already have pattern matching pattern uses that are based on other reflective models such as instanceof
, Array.isArray
or testing the existence of a property etc. Will this fit in well with that?
Is this even necessary because VMs will typically test and branch on the hidden class instead? Can another model that doesn't predefine a fixed enum of values be used? Probably.
Syntactically, more could be done, enabling a few useful applications:
Library that implements this functionality in ES6: https://github.com/rauschma/enumify