JS2 Design Notes

Goals

Here are some design notes for JS2, starting with my goals, shared in large part by ECMA TG1 for ECMA-262 Edition 4:

  1. Support programming in the large with stronger types and naming.
  2. Enable bootstrapping, self-hosting, and reflection.
  3. Backward compatibility apart from a few simplifying changes.

(Goal 2 implies many things beyond what is discussed in these notes.) Non-goals, again shared (mostly!) by ECMA TG1 going back to Waldemar’s Edition 4 drafts:

  1. To become more like any other language (including Java!).
  2. To be more easily optimized than the current language.

Types

In JS today, every expression has a type, as specified by ECMA-262 Edition 3
Chapter 8. The visible types, by their spec names, are Undefined, Null, Boolean, Number, String, and Object. These types are disjoint sets of values:

Undefined = {undefined}, Null = {null}, etc.
Int32 and UInt32 are subsets of Number (IEEE-754 double precision) subject to
different operators from Number, and they appear only in the bitwise operators,
Array length, and a few other special cases.

Edition 3 Chapter 9 defines somewhat ad-hoc, mostly useful conversion rules between types. Chapter 15 contains constructor specifications that may also convert according to the Chapter 9 rules, or ad-hoc variations on those rules.

One oddness to JS1: the so-called primitive types Boolean, Number, and String each have a corresponding Object subtype: Boolean, Number, and String respectively. When a primitive value is used as an object, it is automatically “boxed” or wrapped by a new instance of the corresponding object subtype. When used in an appropriate primitive type context, the box/wrapper converts back to the primitive value.

For JS2 and ECMA-262 Edition 4, we would like to use modern type theory to avoid the pitfalls and contradictions of less formal, ad-hoc approaches. We define a lattice of all type value sets induced by the set contains
subset
relation, in order to:

  1. Define new operators to enable programmers to test and enforce invariants using type annotations (goal 1).
  2. Let users define their own types by writing class extensions that can do anything the native classes can do (goal 2).
  3. Eliminate primitive types and boxing, coalescing each Edition 3 primitive type with its object wrapper (simplifying exception from goal 3).
  4. Provide nullability and rationalize Undefined (goals 1 and 3).

The lattice is as follows, with arcs directed downward by default (arcs directed otherwise have an arrowhead showing direction):

___⊤___
/       
/         
Void        Object?__________
/               
/                 
Null<----String?    Object__________
     /   |           
   /    |            
String  Number  Boolean  User...
(double)
/  |  
/   |   
int  uint  ...

⊤ is the top type, not named T in the language. Edition 3’s Undefined is renamed to Void, as in Waldemar’s Edition 4 drafts.

For all object types t, there exists a nullable type t? = t ∪ Null. Only Object? and String? are shown above, but every object subtype is nullable. Note that this is just a specification notation; we have not committed to adding the ? typename suffix for nullability to the language.

The User… type stands for a hedge of user-defined type trees. I’ve left out Array, RegExp, Date, etc., because they can be thought of as
user-defined Object subtypes. Also, not all proposed numeric types are shown (not all are subtypes of IEEE double).

Type operators

Given a value and a type, you can ask whether the value is a member of the type’s set using the is relational operator:

v is t ≡ v ∈ t's value set ⇒ Boolean

A class defines an object type, and class C extends B {...} defines a subclass C of base class B. All values of a subclass type are members of its superclass type, so (new C is B).

Given a value of unknown type, the as relational operator coerces (or downcasts) the value to the type, resulting in null if the value is not a member of the type:

v as t ≡ (v is t ? v : null) ⇒ t?

So, e.g., undefined as Object === null — this shows how the type of an as t expression is t?.

Given a value of arbitrary type, the to relational operator converts the value to be a member of the nullable extension type, or throws a TypeError exception.

v to t ≡ (v is t ? v : v converted to t) ⇒ t? or throw TypeError

The to operator may result in t rather than t?, at the discretion of the class implementing t (e.g., null to Boolean === false). A class may define its own to operator using the following syntax:

class C extends B {
...
function to C(v) {...}
}

We will redefine the type conversions specified variously in Edition 3 Chapters 9 and 15 in terms of the to operator applied to the native classes.Our current thinking is that to conversions follow Chapter 9, except for any of (Null ∪ Void) to (String ∪ Object), which all result in null, not "null", "undefined", or a TypeError throw.

Type annotations

Testing and enforcing invariants using these type operators in expressions governing control flow is sometimes useful, but often tedious, error-prone, and bloaty. We wish for typed declarations that enable the language implementation to do the testing and enforcing for us. Therefore for each of the three type operators is, as,and to, there is a corresponding type annotation that may be used with var, const, and function declarations to specify type:

var v is t = x ≡ if (!(x is t)) throw TypeError; var v = x
var v as t = x ≡ var v = x as t
var v to t = x ≡ var v = x to t

The initializer is optional as usual; if missing, a sane default value for the annotated type is used. For all assignments v = x following such a type-annotated variable declaration, the production on the right of ≡ above, stripped of var, is evaluated. Function formal parameters and the function’s return value may be annotated similarly:

function f(a is int, b as Object, c to String) is Number {...}

Type annotations are optional. To support strict options that require every declaration to be annotated, * may be used for ⊤ (the top type), e.g. var v is *, which is equivalent to var v. Note that * is used differently for E4X, but its meaning as ⊤ is unambiguous in type operator and annotation right operand contexts.

In a nutshell, is t annotations insist on type t and defend against null and undefined (no more “foo has no properties” errors; with static analysis, an error that can’t be avoided at runtime can even be reported at compile time). as t annotations enforce (is t)-or-null invariance. And to t annotations convert according to cleaner, class-extensible rules.

Coming soon

In the next update, I’ll list the small number of incompatible changes to Edition 3 that we are considering. In a subsequent item, I will discuss stronger naming mechanisms to support programming in the large.

23 Replies to “JS2 Design Notes”

  1. This looks very promising though I have some concerns.
    Eliminating the concept of primitives and boxing is a good step toward simplifying the language, but it may induce break backwards compat, especially with the “typeof” and “instanceof” operators.
    var a = 10;
    typeof a // returns “object” or “number”?
    a instanceof Number // returns true or false?
    Your datatype syntax proposals break compatibility with the latest versions of ActionScript and JScript, both of which use the syntax:
    var obj : String;
    instead of using “is”. I’m not saying this breakage is a no-go, but MS and others might be loath to add redundant functionality to their languages.
    The new “is” operator also makes the “typeof” and “instanceof” operators redundant (with the elimination of the distinction between primitives and objects).
    Concerning type conversions, what role will toString() and valueOf() now have, with the new “function to” syntax? Will it be possible to use this new syntax to add a type conversions to existing objects or prototypes along the lines “foo.toString = function()…”?
    Also, that lattice diagram is rather confusing with those “nullable types”.

  2. I agree with Bryant Chen. While it may not be as innovative, following the lessons learned in other ECMAscript-4-like languages, like Actionscript2, is likely a good starting point.
    Certainly, where you have a few syntax choices, sticking with what other languages have done is a good thing (like using post-colon notation for types instead of adding a new “is” keyword to the language, which WILL lead to compatibility issues). In the past I’ve enjoyed using the same code in Flash and Javascript. I’d like to do that again in the future.
    Ultimately, there are two audiences for JS2: Mozilla developers (including extension authors) and web developers. The former benefit from most any innovative improvements to the language. But the latter suffer unless those improvements are reflected in other browsers. Furthermore, the former category may be better served by the addition of established languages (like Python) over custom enhancements to Javascript.
    Chris

  3. Bryant: typeof 42 will continue to result in “number” in Edition 4, and similarly for other primitive type values. There is no reason to break compatibility here.
    Howeover, my next post will discuss a typeof corner case where we would like to break compatibility. I’ve mentioned it before, so it’s no surprise: typeof null == “null” instead of the current “object”.
    typeof is a mess, neither well-defined in practice for Edition 3 object subtypes (see https://bugzilla.mozilla.org/show_bug.cgi?id=305959 and https://bugzilla.mozilla.org/show_bug.cgi?id=289933), nor extensible to Edition 4 classes. We will keep it for compatibility, but leave it (mostly) alone.
    Likewise, instanceof does not change. It continues to check whether the prototype property of the right operand (required to be a constructor function or class) is on the __proto__ chain of the left operand. There is no reason to change instanceof, but note that instanceof is not the same as “is”:
    // Edition 3 constructors.
    function A() {}
    function B() {}
    function C() {}
    B.prototype = new A;
    C.prototype = new B;
    var c = new C;
    print(c instanceof Object); // true
    print(c instanceof A); // true
    print(c instanceof B); // true
    print(c instanceof C); // true
    print(c is Object); // true
    print(c is A); // false
    print(c is B); // false
    print(c is C); // false
    // SpiderMonkey only: instanceof relation is not fixed.
    c.__proto__ = new B;
    print(c instanceof C); // false
    // Edition 4 classes.
    class AA {…}
    class BB extends AA {…}
    class CC extends BB {…}
    var cc = new CC;
    print(cc instanceof Object); // true
    print(cc instanceof AA); // true
    print(cc instanceof BB); // true
    print(cc instanceof CC); // true
    print(cc is Object); // true
    print(cc is AA); // true
    print(cc is BB); // true
    print(cc is CC); // true
    Note well how Edition 4 classes permanently bind instances to class “traits”, so that script cannot change the meaning of “is” or “instanceof” for a given class instance. In Edition 3, only native and host classes written in the implementation/host language(s), and not user-defined constructor functions written in JS, could make such permanent type bindings. Such bindings are important for security, reliability, and programming in the large.
    Note also that “is” and “as” have been in Edition 4 drafts all along, and show up in ActionScript and JScript (“as” in pre-Edition 4 implementations may not match these design notes exactly).
    As I wrote in the first paragraph, this design work is being done with other ECMA TG1 members. Macromedia folks are involved, and Microsoft is represented in ECMA TG1. If you are pessimizing the language design by fearing that design-by-committee will limit what is possible to what was implemented based on old drafts, you’re taking the wrong approach. We won’t get another bite at this apple — it’s time to get JS2/ES4 right. I am not going to participate in a rubber-stamp process, and neither are the other TG1 members, as far as I know.
    Again, backward compatibility is a goal. New JS2/ES4 code can select strict options and enable incompatibilities, but for ease of implementation and code migration, we are changing as little as possible in the existing language. The best way to ensure compatibility is to leave things like instanceof *alone*, and define stronger universal type operators appropriately.
    The colon-style (:String, e.g.) type annotations in ActionScript, based on the older Edition 4 drafts, are alternate syntax for “to” annotations. This became clear working with the Macromedia folks, and it led to further thinking about types. (BTW, : cannot be used as a type operator, due to ambiguity with labels and conditional (?:) expressions, so “to” is the new syntax, and pre-Edition 4 implementations can keep : annotations for their own compatibility.)
    Given types, you can assert (is), coerce (as), or convert (to). Conversion alone is not enough, since it either leaves null unconverted, which is a “foo has no properties” hazard that one should be able to assert against with an annotated declaration; or conversion changes, e.g., null to String “null”, which may be acceptable with dynamic types only (Edition 3 and earlier), but which is wrong with asserting and coercing annotations such as “var str is String” and “var strOrNull as String”.
    Since “to” converts rather than asserts or coerces, it is not sufficient as the only kind of type annotation.
    Hence the symmetry between the type operators and annotations. Failing to provide an annotation for a type operator gratuitously forces programmers to hand-code constraints, instead of letting the type system do the work.
    Regarding the type lattice, it may help to think about the type of the “as” expression, which is akin to dynamic_cast in C++, “as” in C#, etc. It checks type at runtime and returns either null or its left operand, appropriately coerced to the type given by its right operand. Since every expression has a type, the type of “as Object” is therefore Object?, not Object. It’s important to model nullable types in the type system, since we want the following to hold:
    print(undefined is Object); // false
    print(undefined as Object); // null
    print(null is Object); // false
    print(null as Object); // null
    If you don’t have an Object? type, then either Object is the top type, which contradicts both “is” results and the first “as” result. Or else Object must contain null (must be nullable by definition), which contradicts the second “is”, as well as the decade-old definition of an object as a collection of properties.
    If you are interested in type systems, I highly recommend Benjamin Pierce’s book (TAPL, linked in my blog).
    /be

  4. Chris: here are some comments that should help:
    * The type system design has indeed learned from ActionScript experience. The ActionScript design work based on Edition 4, and moreover the user testing done by Macromedia, were both invaluable in re-axiomatizing “to” (:) annotations.
    * “is” and “as” are already in Edition 4 drafts, and have been for a long time. But since it is not necessary to reserve these keywords, there is no compatibility problem.
    * Other languages such as Pascal use var v:t type declarations, not annotations, but JS does not descend from Pascal. It would be more in keeping with C and its progeny to use var t v, but this is ambiguous with missing-single-token error cases, and more important, it’s not consistent with the asserting (is), coercing (as), and converting (to) type operators. Again, I refer you to the first non-goal.
    * In the future, per discussions with Macromedia folks on TG1, you will be able to use “to t” annotations instead of “:t” in ActionScript — provided the new design presented here is standardized as Edition 4 (and I expect it will be). As I noted in my reply to Bryant, Macromedia will keep :t support for backward compatibility.
    * We’re adding optional C-Python support for XUL extensions, but we are not going to bloat Firefox with C-Python for Windows users, the vast majority of whom lack the runtime. Extensions are not just for narrow segments of fans. Similarly, we are adding Java/XPCOM bridging to XULRunner, but we can’t count on Java for the masses.
    * JS2 has its own _raison d’etre_, on the Web and in Mozilla’s platform. The programming in the large goal applies equally well to “AJAX” and DHTML libraries as to XUL extensions and apps. JS must evolve or die; coasting is not an option. Once Edition 4 is finalized, I expect other browsers to implement it.
    /be

  5. I wanted to credit Edwin Smith of Macromedia with the nice special form by which a class can define its own “to” operator:
    class C extends B {
        …
        function to C(v) {…}
    }
    This follows the function get and function set forms in Edition 4 drafts for getters and setters. Ed also proposed
        function call C(…) {…}
    as the special form to use when defining class C’s constructor called as a function (see Boolean, Number, String, Date, Array, etc. special cases in Edition 3 Chapter 15).
    To make the constructor-called-via-operator-new form stand out when juxtaposed with the constructor-called-as-function form, Ed suggested allowing but not requiring
        function new C(…) {…}
    This unreserved call keyword suggests to me a natural syntax for __noSuchMethod__, AKA the “default call” hook:
        function call *(id is String, …) {…}
    where id gives the method identifier that was called.
    I’ll summarize all of this in a future post.
    /be

  6. Regarding
    var v is t = x ≡ if (!(x is t)) throw TypeError; var v = x
    var v as t = x ≡ var v = x as t
    I ignored something that is even written on my whiteboard, right in front of me, when I then wrote:
    “The initializer is optional as usual; if missing, a sane default value for the annotated type is used.”
    For “as” and “to” annotations, null can be used because it is in the value set for all possible result types (“as t” and “to t” have static type t? if no TypeError is thrown).
    For “is” annotations, null and undefined are not values of any named types. Further, for Object and subtypes other than the primitive types, we do not want to construct a new instance as a default initializer. Construction is a potentially high hidden cost, and it could have side effects.
    So “is” annotations require initialization: “var v is t = x”. What’s more, forward reference in the same class, function, or global scope to the “is”-annotated variable must be illegal, because undefined is not a legal value.
    This redresses another strangeness in JS1/ES1-3: the way that variables are hoisted to top of their function body or global scope. With “is” annotations, the only remaining effect of the hoisting is to disallow references to an outer scope binding of the same identifier. Example:
    var x = 2;
    function f() {
        print(x);
        var x is int = 42;
        print(x);
    }
    f()
    In Edition 3, removing the “is int” annotation, you would get undefined and 42 from the prints.
    With the proposed Edition 4 rules, you’ll get a TypeError from the first print.
    In no case could the first print refer to the global variable named x.
    Given the compatibility goal, we can’t change the way variable scope works. But we *could* consider adding first class blocks in order to add block scope. In Edition 3, you have to nest functions to nest scopes (lambda as the ultimate scope tool ;-). With first-class blocks as more efficient and concise nested functions, we could make var behave the way many hackers expected it to.
    I’m not sure what a first-class block syntax would be. It has to be nearly as easy and sweet as {}.
    Comments welcome.
    /be

  7. From what I can see, JS2-style classes and JS1-style constructors will have many differences. By differences, I mean classes can do many things that constructors can’t and vice versa, so a constructor and its prototype can’t hack up a class, and a class isn’t as (dangerously) flexible as a constructor.
    Can you list the key differences between the two, besides syntax? It seems like an object instantiated from a class can’t have it’s __proto__ changed, since that could mess up the “is” operator, and constructors can’t use the private and protected modifiers for members.
    Ideally, we’d use classes for everything, but there are obvious cases where extending the prototype is needed. The typical case: modifying a built-in class such as Array, ideally without affecting for-in.
    Speaking of for-in, IMHO that statement is rather clumsy. It would be much more useful if for-in could use a user-defined iterator. In fact, it would be nice if each class had a default iterator, such that “for (i in obj)” would get this default iterator, and this iterator could be modified. That would make for-in more applicable to classes besides Object.
    I like that new “function call C” and “function new C” syntax. Very elegant and it avoids the problem of conflicting with methods with non-keyword names, e.g. function call(…)”. Going back to the class vs. constructor issue, can (and how can) this be done with a constructor’s prototype?
    Concerning “__noSuchMethod__”, what we need is a more generic “__noSuchProperty__” that can return a Reference (as defined in the ES spec) for method calls and assignment.
    Concerning JS1’s var “hoisting” as you call it, perhaps that feature could be one of the things disabled under the “strict” setting.
    AFAIK, the last public ES4 draft had “{” and “}” introduce scope, but you seem to be indicating this is no longer the case. I have a suggestion: how about “{{” and “}}”? I can’t think of a case where someone would have an unlabelled block statement as the sole statement of another block statement, and it shouldn’t be possible to confuse this with an object literal, since “{{” and “}}” in JS1 is already always interpretted as a block statement within a block statement.

  8. Bryant, some quick replies:
    – Classes are sealed, not dynamic, by default. You have to say “dynamic class C … { … }” to regain the Edition 3 dynamism. Otherwise class members are fixed and always shadow prototype properties of the same name.
    – You’re right in wanting iterators. One easy step is to follow Python, expose an iterator meta-object protocol, and base for..in on it. Not only for..in, but Python-like generators, including array comprehensions. More on iteration in a separate post.
    – There’s no need for __noSuchProperty__ given function get *(id is String) {…} and likewise for set. As with call, * should be usable to mean any identifier and the id actually used is passed in. But we have __noSuchMethod__ already, and it is inspired by other languages that all provided what people want: a default call handler, not just an unknown property handler.
    The call case merits a special form, rather than a flag to the default getter. The call form can actually do the call, using named and/or rest params. If the default getter is the only way to implement default call handling, it will have to add functions to the instance or its prototype and let the engine dispatch. These added functions are gratuitous bloat.
    BTW, in Object Initialisers, Edition 4 should support get, set and call shorthands (no function keyword before-hand), as SpiderMonkey does today for get and set (soon for call too, if shaver hacks it).
    – I am personally not in favor of a strict setting changing variable scope rules except to flag bad practices. So I don’t think we should have any such strict option change how hoisting works, but we might flag forward references as errors.
    – The var local = “hi”; {{ var local = “hi”; }} print(local) => “hi” idea is good, thanks. I thought of it but didn’t like the look of the doubled {{, but it is growing on me. I’ll try it out on the rest of ECMA TG1.
    /be

  9. Oops, cut-paste error here:
    – The var local = “hi”; {{ var local = “hi”; }} print(local) => “hi” idea is good, thanks.
    Obviously the block should be {{ var local = “bye”; }} or some other string initialiser than “hi”.
    /be

  10. AS2 uses __resolve for __noSuchMethod, returning a function reference which then is invoked, why not keep the same syntax? Also, I’m not sure why you’re referring to “:” as the “to” operator. In AS2, types are only inforced at compile-time, with special methods toString and toNumber specifying the conversion rules to these (and only these) types. Using : does not perform any type of implicit type conversion, you have to surround the right hand side in the class name as in Java.
    I know AS2 is not the beginning and end of ECMA4 but cross-compatibility would be interesting considering the massive amount of libraries already written in AS2.

  11. __noSuchMethod__ is a SpiderMonkey extension, not something proposed for Edition 4 in that form. It has precedence, so does __resolve in AS2. Neither is likely to be standardized as is. The point of mentioning __noSuchMethod__ was the idea, not the exact form and syntax.
    Types may be enforced only at compile time in a version of AS2, but I’m told by ECMA TG1 colleagues from Macromedia (now Adobe) that : converts at runtime in the default dialect (not compiling with a “strict” option). Converting is not the same as coercing or asserting. Having conversion via special methods only for number and string (why not boolean or user-defined object?) is not the same as enforcing types.
    Converting in some cases, coercing or asserting in others, all depending on whether a default or strict compilation mode is used, makes a hash of what are useful, orthogonal language features. Even in a single compilation unit, one should be able to assert or coerce at API boundaries but use converting annotations internally as appropriate.
    Anyway, AS2 is old hat, and AS3 is the version that is being adjusted to be forward compatible with Edition 4. Edition 4 is not going to be a rubberstamp on AS-any-version.
    /be

  12. In case it isn’t clear, coercing (“as” annotations) yields nullability for all types in a universal way. Asserting (“is”) gives strictness, so invariants don’t have to be enforced by (buggy or missing) code. Converting is soft and fuzzy, and seems popular.
    I mentioned wanting to mix annotations for API compatibility, with old APIs converting but using assertions and coercions internally. The other way around is likely too: new APIs that are mostly or totally strict (“is” annotations) at their method boundaries, but which might use coercing and converting annotations internally.
    /be

  13. “BTW, in Object Initialisers, Edition 4 should support get, set and call shorthands (no function keyword before-hand), as SpiderMonkey does today for get and set (soon for call too, if shaver hacks it).”
    That doesn’t answer my question of how such functions can be added to a constructor’s prototype or object. I know SpiderMonkey supports the following syntax:
    obj = {get prop() { return “hi” }};
    //…
    print(obj.prop); // “hi”
    (IMO that syntax is inconsistent with the object literal syntax since it lacks a colon, but that’s another issue.)
    But that can’t be done after the object is created. You can’t do something like:
    obj.prop = get() { return “hi”; }
    I’m using getters as an example, but this applies to all special functions, including the proposed new ones (get*, set*, to, call).

  14. Bryant: long story here. I originally added getters and setters in a consistent and complete way. You could define them in an object initialiser:
    obj = {prop getter: function(){return “hi”}}
    Or you could set them after the object was created:
    obj.prop getter= function(){return “hi”}
    You could also declare a getter or setter function:
    getter function prop() {return “hi”}
    Likewise for setter (setter:, setter=, setter function). Apart from the “-ter” verbosity, this satisfied your reasonable requirements:
    1. A colon separating some kind of property id from its value in object initialisers.
    2. A way to assign a getter.
    I didn’t allow delete or lookup methods, however.
    During ECMA-262 Edition 3 construction in TG1, IIRC, this form was shot down. I don’t know the details, but I recall Waldemar wanted to avoid differing from the JS2/ES4 draft, which allowed only one form of getter, in a function declaration (a method declaration if in a class body):
    function get prop() {return “hi”}
    So it was decided to embed everything after the function keyword as an alternate kind of property initialiser in object initialiser syntax. This was implemented in SpiderMonkey in addition to the getter: form.
    To dissuade people from using the getter= form, __defineGetter__ was added, along with __lookupGetter__ (ditto for Setter, of course).
    Since SpiderMonkey supports both my original and the proposed (or were they just future-proofed against proposed ES4 syntax? hmm) forms, we have no strong stake in which one is standardized (we’ll have to carry support for both forever). So, we could go back to ECMA TG1 and raise your requirements. The semantics have to be written carefully (consider DontDelete properties).
    /be

  15. I agree with Brendan re: __noSuchProperty__.
    Example:
    I want to create an ArrayAdapter object, which calls registered callbacks when elements of the “array” are changed/read.
    The closest I can get at the moment is to create a ‘new Object()’, give it an Array propery, install __noSuchMethod__ on it, and test for numeric method id’s in the handler.
    Unfortunately the syntax is not quite natural for arrays:
    alert(aa[2]()) // show 3rd element
    aa[4](5) // set 5th element to 5
    __noSuchProperty__ would allow me to completely emulate the semantics of an Array object.

  16. Hurray for nullable types! I hope they make it into the language. It is _so_ important that null not be a member of every type if you want to do type inferencing.
    But I hope there is a type-oh in your description of the `to` operator. If you are going to throw an error if the object is not an instance of the target type, then there is no reason for the result to be a nullable type (unless the target is). Thus
    v to b
    should either throw an error or return a `b`. If you want to permit `v` to be null too, you should say:
    v to b?

  17. One of the really cool aspects of js1.x is it’s functional capabilities. Since I often find myself typing function() { over and over, a nice addition would be a short way of declaring a lambda (anonymous function). There are plenty of unused special-symbols to pick from, for example :

  18. Hmm … i am wondering about overloading.
    It is not part of ecma definition, afaik. Its not part of AS2 or AS3, but I still think that the concept of a typed language without overloading can’t be in the mind of the creator (i’ve worked a lot with AS2). The concrete point i have problem is the case you treat all methods same, then you need to safe the arguments.
    fX = function(a,b) {}
    fX(“a”); // not allowed, who complains?
    instX = new Clazz();
    instX.a = function(a,b) {}; // not allowed because of wrong type?
    Whats about the arguments object in those cases?
    Once upon a time there has been a storage(array, forgot the name) for all variables defined in a method.
    Okay, another thing is that haXe.org is working on a type definition for the DOM structure, and Nicolas(creator) got confused by the differences of the JS DOM implementations (in its detail). Maybe this can be used for communication.

  19. How about:
    obj = {‘get foo()’: function () { return ‘hi’ };
    obj[‘get foo()’] = function () { return ‘hi};
    as the ‘non-class’ way to declare getters. Similarly:
    obj[‘set foo()’] = function (newvalue) { this.foorep = newvalue;}
    ?

  20. ptw: We’ve already shipped the
    obj = {
    get foo() { return this.val },
    set foo(nv) { this.val = nv }
    }
    form for years, based on agreement with waldemar when he was drafting Edition 4. ECMA TG1 has bought into this. What you propose has the nice property that it conserves the id: value property initializer syntax, but ids with spaces are legal, so it’s not strictly backward compatible (e.g., someone may be using an id such as ‘get foo()’ to hold a function value, and not want that to define a getter).
    /be

  21. I have a few questions, first of which is why are you still introducing classes? I don’t think they’re any benefit. The prototype based object model works, and it works very well. It’s very flexible, and it’s very purely OO.
    Second is to what value do value type constraints give us?
    If you are going to introduce classes, why not consider introducing multiple inheritance? The current model makes multiple inheritance tricky to approach.
    I really hope you folks don’t screw this up. I still don’t believe that this is really headed in the right direction. I don’t think JavaScript should be focused on becoming a programming in the large language. Not that it’s not a good language, and maybe even a focus on becoming more general purpose is good, but why do we need to add so many features becoming of Java and everything else in order to become more general purpose? What benefits to type constraints give us…compile time contracts? Are we really concerned about compile time contracts in an environment designed to be runtime compiled in a plugin to a web browser? And will compile time contracts actually make it easier to build stable software? (The answer to the last one is not really, I know this from experience)
    I take this approach for a reason, while I would like to see more general purpose applications of JavaScript, the lack of such currently has little to do with the syntax itself of the programming language (in my opinion) as it stands in JS 1.6. Most of it has to do with that no one has dedicated the time toward providing a general purpose scripting environment based on JavaScript the other features it would need to be beneficial (Good IO interfaces, a Database Interface, good system call interfaces, etc!)
    I have a set of rants about the waldemar js 2 proposal that actually transcends into what you have here, also http://www.blisted.org/wiki/papers/opinions/JavaScript2.0

Comments are closed.