On Mar 24, 2008, at 6:45 PM, Mark S. Miller wrote: > Now on to your real question. Why do I seem to believe that proposed > ES4 is statically typed? A fair question. Proposed ES4 lies somewhere > between the simple categories of "statically typed" and "dynamically > typed". However, rather than finding a happy compromise between the > two, it mostly combines the worst of these two worlds.
That's a charge you have yet to demonstrate. It's ironic to read your charge that ES4 is statically typed, just after reading Matthias Felleisen in Steve Yegge's blog comparing "Proposed ES4" to TypeScheme and criticizing ES4 because it does not impose a static type system on JS. > It pays most of > the costs of static typing but obtains few of the benefits. How do you know this? > And it > inherits all the costs of having been dynamically typed, but retains > few of the benefits. How did you use "Proposed ES4"? Did you write programs in it? > Benefits of Static Typing > > * static assurance that type mismatch errors will not happen at > runtime > * runtime space savings > * runtime time savings > * type-based IDE refactoring support (as in IDEA and Eclipse) Or Flex Builder, which emits a rough subset of "Proposed ES4". Or once upon a time ASP.NET emitting JScript.NET. The same retort (we are operating at a crude level of rhetoric here, almost fact-free, but I'll play along) applies to your other three bullet points above. > Costs of Static Typing > > * language complexity And over-minimizing a language imposes a complexity tax on programmers using it. This happened long ago with JS1 and it was compounded by foot-dragging monopolist misconduct since 1999. To decide whether to evolve JS or shrink it, you need only look at two things: 1) problems JS hackers run into every day, which are not solved by more idiomatic functional programming hacks that add cycle and space bloat to their libraries and applications; 2) competition from other languages in runtimes vying to displace the browser. > * limit expressiveness to statically checkable type "predicates". > :int, but no :prime Not for want of trying: see http://wiki.ecmascript.org/doku.php?id=proposals:contracts Still possible in ES5 after we finish ES4. I would like to point out that PLT-style contracts are *research*, and we've been criticized without justification for "doing research" in ES4. Why are you promoting contracts when the research has not been reduced to efficient practice yet, and AFAIK depends on a module system to keep the contracts on the outside of modules, not on the inside? > * two "expression" languages - static type expressions vs dynamic > value expressions That's a fair point. In order to support an *optional* static checker, the ES4 design restricts type expressions. Why this is a hardship has yet to be demonstrated, since your preferred style of language offers zero type checking at runtime (or optionally at compile time). If you are arguing the static side of the equation, please cite statically typed languages that allow full value expressions as types. I know of research languages, but besides having undecideable type systems, they are (again) *research*. > * multiple partial type theories: nominal, structural, duck, ... The inclusion of a structural type system is a virtue, since untyped objects are common on the web even in the face of the nominal DOM and browser object types, and since no one can revise all code entangled on the web to use nominal types, at once or even ever. I don't know what you mean by "duck", it's ill-defined and generally unsound when used in other languages. Structural types address the latent typing disciplines used in current Ajax libraries, JSON schema, etc. > * verbosity On the contrary: // Version 1 of a webmail client, in pure ES3 function send(msg) { validateMessage(msg); msg.id = sendToServer(JSON.encode(msg)); database[msg.id] = msg; } function fetch() { handleMessage(-1); // -1 means "get new mail" } function get(n) { if (uint(n) !== n) // JS1: n>>>0 === n throw new TypeError; if (n in database) return database[n]; return handleMessage(n); } var database = []; function handleMessage(n) { let msg = JSON.decode(fetchFromServer(n)); if (typeof msg != "object") throw new TypeError; if (msg.result == "no data") return null; validateMessage(msg); return database[msg.id] = msg; } function validateMessage(msg) { function isAddress(a) { return typeof a == "object" && a != null && typeof a.at == "object" && msg != null && typeof a.at[0] == "string" && typeof a.at[1] == "string" && typeof a.name == "string"; } if (!(typeof msg == "object" && msg != null && typeof msg.id == "number" && uint(msg.id) === msg.id && typeof msg.to == "object" && msg != null && msg.to instanceof Array && msg.to.every(isAddress) && isAddress(msg.from) && typeof msg.subject == "string" && typeof msg.body == "string")) throw new TypeError; } // ES4 version of same: type Addr = { at: [string, string], name: string }; type Msg = { to: [Addr], from: Addr, subject: string, body: string, id: uint }; type MsgNoId = { to: [Addr], from: Addr, subject: string, body: string }; function send(msg: like MsgNoId) { msg.id = sendToServer(JSON.encode(msg)) database[msg.id] = msg wrap Msg } function fetch() handleMessage(-1); function get(n: uint) { if (n in database) return database[n]; return handleMessage(n); } function handleMessage(n) { let msg = JSON.decode(fetchFromServer(n)) if (msg is like { result: string } && msg.result == "no data") return null return database[msg.id] = msg wrap Msg } $ wc /tmp/*way 30 102 688 /tmp/newway 47 177 1302 /tmp/oldway 77 279 1990 total ES3 code shrinks when rewritten in "Proposed ES4". > (inside Google, we've expanded to a 100 column limit for > Java generics) (What has that to do with anything but Java as used inside Google? There's no point in arguing about behind-the-firewall non-evidence.) > * inappropriate for casual scripting audience ES3 is a subset of "Proposed ES4" and supports evolution and code migration, along with single specification and implementation (critical on small-device browsers). Beliefs about "Proposed ES4" and what is appropriate for "casual scripting audience" members need demonstration, not assertion. > Benefits of Dynamic Typing > > * lambda abstraction / objects is all you need We know that lambda is all you need. Why bloat things with objects? For that matter, why speak English instead of Standard Business English, the subset Guy Steele made up for his "Growing a Language" OOPSLA '98 talk, or Esperanto? > * Tennent correspondence > <http://gafter.blogspot.com/2006/08/tennents-correspondence- > principle-and.html> Java closures are years late and mega-dollars short of the mark, compared to first-class functions and closures. Perhaps you agree? > * all abstractions first-class, composable That's our goal too, but you'll have to study "Proposed ES4" to show us where we've failed, instead of citing irrelevant Java non-evidence. > * simple meta-interpreters can enable powerful meta-programming I'm not sure what you mean. Could you give an example? I wrote a meta- circular ES3 interpreter in a superset of ES3 (SpiderMonkey extended to host and boostrap Narcissus), but I don't know what you are implying cannot be done by ES4, or can be done better, or exclusively, by ES3 here. > * syntactic simplicity supports other metatools: minifiers, lints, ... Syntax is also user interface, and again minimizing it too much makes programming harder. If this bullet were overriding, we'd be using S- exprs. > * rapid prototyping Done all the time using ES3 and "Proposed ES4" approximations and piece-wise implementations, some already shipped (JS1.8 in Firefox 3 beta), some much closer to ES4 being implemented now. > > Costs of Dynamic Typing > > * runtime space and time costs Space costs are indeed an issue. I am happy to ignore time costs, and stipulate that they can be reduced to noise by clever optimization techniques for most cases. > * less static knowledge of dynamic behavior A lot less ;-). > Benefits of Soft / Gradual Typing > > Proposed ES4 and some dynamic languages share some of the advantages > of soft typing systems. A soft typing system is, essentially, a > dynamic typing system with a convenient syntax for declaring type > checks that should be checked at runtime. Have you read anything about 'like' types in "Proposed ES4"'s overview document or evolutionary programming tutorial? > * Better documentation of expected interfaces - better project > coordination > * Fail-fast runtime behavior > * easy transition from rapid prototypes to production These bullets all arguably apply to "Proposed ES4". > Benefit of Soft Types absent from Proposed ES4 gradual types: > * type "predicates" are any runtime test expressible in the language This is a selective argument, since (a) we have structural types and 'like', which cover common cases (common meaning probably > 80%, but to be demonstrated, I admit); (b) we can add contracts in the future if the need arises *and the research is "done"*. > Classes as > Sugar > > Given something like the __createProperty__ (__defineProperty__ in the latest spec, FYI.) > we > give integrity to this use of nominal typing. The proposed ES4 type > declaration syntax could then expand to simple nominal type checks: > > var x :C = ...; > > expands to > > var x = Object.cast(C, ...); > > where > > Object.cast = function(type, value) { > if (value instaceof type) { return value; } > throw new TypeError(...); > } What is the point of all of this? I can map ES4 to ES3 too, and so can others -- some are even building translators. But programmers should (a) not have to do this by hand; (b) not have to procure and use an offline ES4 to ES3 translator to reap the benefits of ES4, except for the transparent debugability (instead, they get leaky-unto- flooding-abstraction hell). > One further suggestion to make the class syntax more convenient: Get > rid of separate constructors. Instead, allow parameters after the > class name which are then in scope in the class definition. This was considered too, see: http://wiki.ecmascript.org/doku.php?id=discussion:nullability#example I like the first part -- constructor parameters in the class head. The odd-looking special form "function Foo { ... }" for the constructor code loses compared to an intact constructor function, though. > With the expansion above, we seem to have only implemented a subset of > proposed ES4 providing only nominal types. Sure, it's simpler. But how > is it more expressive? Unlike proposed ES4 classes, the expansion > above is lexically nestable and multiply instantiable. This provides > the flexibility of a runtime trademarking system, where the program > can create as many trademarks as are dynamically needed at runtime. I favor allowing classes in "Proposed ES4" to be nested in functions, for what it's worth. Since we aren't done yet, perhaps this will come to pass, although "lexical nestability" is not a burning issue in general. "Multiply instantiable" is indeed relevant on the web with various window objects and browser-specific sandbox objects hosting instances. We can do better, but so could your example. There's no reason to force everyone to write, or translate to, a minimally extended ES3 and suffer the performance and debugging consequences. > The key to the correctness of the above code is that every call to > makeBrand create a distinct nominal Envelope type, In ES4 as proposed you can use eval to make distinct nominal types. /be _______________________________________________ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss