Brendan Eich (2013-07-29T03:43:14.000Z)
domenic at domenicdenicola.com (2013-08-12T05:19:26.938Z)
Axel Rauschmayer wrote: > A bit uneasy about typeof, which will never properly express JavaScript’s “class” hierarchy. What class hierarchy? primitives have wrappers but those are not what typeof tests. If you believe ``` Object | +-------+-------+----+----+----... | | | | Boolean Number String Function ``` then where are boolean, number, and string? There's no Value (ValueObject) either. Suppose we build a value object class (constructor/prototype) hierarchy: ``` Object | +-------+-------+----+----+--------+ | | | | | Boolean Number String Function Value | +-------+-------+----+----+------+------... | | | | | boolean number string int64 uint64 ... ``` Would we be better off? Not only is there an abstract Value constructor, but what about double? int32? uint32? In general we would need a semi-lattice like the one depicted here: http://asmjs.org/spec/latest/subtypes.png but without the "-ish", fixnum, and extern types, and with the concrete types listed above. > That is bound to always confuse people (already: “wait – I thought a > function was an object”, worse with value objects). I don't hear that typeof f == "function" confuses people -- that's JS's callable predicate for native (ordinary) objects. I do hear sometimes that people wish typeof a == "array" worked, mainly because instanceof doesn't work cross-frame. Anyway, typeof 0L were to result in "object" we'd have not only confusion but lack of a useful value-type query operator. TC39 agreed on the use-case, and it upholds the (typeof x == typeof y && x == y) <=> (x === y) invariant. > But maybe it’s the best we can do. There is no total class hierarchy describing all values in JS. If you think we should retrofit one, make that case. > Being able to fix typeof null is awesome, though. One could complain that mutating a typeof registry (map-pair) is a hack, but hacks sometimes are the best thing in a pinch, and I don't see a better way. > Also love that we’ll get 64 bit integers etc. (slide 11) and > user-definable value objects. > > W.r.t. to #1: Couldn’t we extend that to universal multiple dispatch? > > ```js > const removeAll = new MultiMethod(); // not a realistic example > removeAll.addMethod(Array, Set, (arr, set) => { ... }); > removeAll.addMethod(Object, Map, (obj, map) => { ... }); > ``` You can do this with proxies and enough work. Operators are special forms already, so have special semantics that I'm generalizing a bit to be only somewhat more special-cased (the *last* special case, a general extension mechanism). Much as I am a fan of dead languages with multimethods, I'd rather leave it at this for ES7. > For the plus operator: > > ```js > import { operatorPlus } from '@operators'; > operatorPlus.addMethod(Point, Number, (a, b) => Point(a.x + b, a.y + b); > operatorPlus.addMethod(Number, Point, (a, b) => Point(a + b.x, a + b.y); > operatorPlus.addMethod(Point, Point, (a, b) => Point(a.x + b.x, a.y + b.y); > ``` This is another way of realizing Function.defineOperator. Is it worth the extra boilerplate? The strong reason to prefer it is to have operatorPlus as a function value to pass around and invoke separately on arbitrary values. One could have both APIs, Function.defineOperator layered on the @operators API. Function.defineOperators was Christian's suggestion and I see the appeal: convenience for users as well as VM implementors (I've implemented it under the hood in SpiderMonkey's int64/uint64 patch).