Kevin Smith wrote:

        (b) ES6 sloppy mode cannot have "let".


    That's overstated, and as such it contradicts the tenuous
    consensus of the last TC39 meeting: to reserve 'let' contextually
    in sloppy mode and evangelize any let [x] = y code out there
    already (which we've yet to find -- 'let' is used as an
    identifier, short for 'letter', but not indexed into on LHS).

    The rest of your reasoning is therefore overstated. It does not
    follow if we can reserve 'let' in ES6, mode-free.


Yes, but see below...

Ok!


    Here I want to refine my Platonic prettiness critique. You talk
    about ES6 as if it can be a thing, which has a timeless existence
    and truth and beauty. Kind of like a dodecahedron -- a pure "Math
    thing".


It most certainly is ; )

Good so far.

    What I think "exists": ES6 as a practical language with a large
    user community who apprehend it in pieces, and sometimes using
    different metaphors or incomplete and even inconsistent "theories"
    or schools of thought. It's a human thing, not a Math thing.


It should *strive* toward truth and beauty. It should approach Math-y-ness. The Math-y-ness is what allows us to cut through all of that human social BS. Anyway, enough of philosophy; more practical stuff below...

The philosophy matters. It's an old debate, Plato vs. Aristotle (remember Crock and me at TXJS 2011?). I'm a realist, and the problems I'm citing are not just "human social BS" -- they involve human factors, usability, stuff that is not social but individual and primal (like forgetting "use strict"; or [for me] forgetting to turn off the Christmas lights each night :-P).


    We agreed at the last meeting to treat 'let' as a contextual
    keyword at start of statement if followed by an Identifier, '{' or
    '['. That is a special case, but so what? 'module' was not
    reserved in ES1-5 so it needs a special case too.


Sure, but as I argued when I read about that consensus, it creates a situation where "let" is a second-class identifier. Either it's an identifier, or it isn't. Any middle ground is, well, sloppy! Not Math-y. : )

Here again we already do not have the ideal as a realistic option.

Consider that 'get' and 'set' are contextual in ES5, but without any backward compatibility issues, and based on syntax extensions from SpiderMonkey that other engines reverse engineered. My point is that ES3 could not future-proof by reserving such short words, and did not need to. No one can foresee all future final/winning best-syntax designs.

And again, ES5 failed to reserve 'module' in strict mode, and ES1-3 never reserved 'module', so ES6 must make 'module' only contextually reserved. We are already in "either it's an identifier, or it isn't" default. If we can do it for 'module', why not for 'let'?

Holding the line at 1 is easier than at 2, but is the line worth holding? For what ideal, given the 'module' exception?

    The spec must serve the users. Not the other way around. Or would
    you give up 'module' from sloppy mode?


Personally, yes. Only modules loaded by the module loader are implicitly strict.

Now I'm confused. What about module M {...} (inline body)? What does "the module loader" mean, the system loader?

Simplicity and elegance are already gone if we're unsure of the conditions for the first exception to the rule. There will be more exceptions over time, based on our concrete experience over the last 16 years of ECMA-262 -- I'm pretty sure!


    Imagine you are adapting existing code, including popular
    libraries not yet in strict mode, to a new app targeting ES6 or
    better runtimes directly, and ES5 and older via a compiler such as
    https://github.com/matthewrobb/six. You are not yet be ready to
    "use strict" in the concatenation of all the code -- there's too
    much risk of breaking something, and never enough test coverage.

    You want to use ES6 features such as rest parameters and
    destructuring right away, before any "use strict" or module
    wrapping. Under your proposal, you can't. You have to multiply
    risks and spend time turning on strict mode, testing harder in old
    and new and middling (IE9, anyone?) browsers.


Sorry, I don't buy it.

If you have a legacy codebase, and you want to use some ES6 features without upgrading the whole thing to strict mode, then you can selectively upgrade the region that you are working on to strict mode by putting "use strict" inside of a function.

And checking whether the function uses |this| and some no caller uses a global reference as the callee expression, intentionally passing |this| bound to the global object. There are other potential gotchas.

If that's too loose-grained, then you shouldn't be fiddling with new features at all.

Says you! :-)

Functions are not all small and simple in real code. Sure, a quick check for arguments, eval, and |this| usage should be enough -- but now I'm not using the new ES6 syntax to solve the problem at hand, I'm off doing strict-mode conversion for Kevin.

What's more, this will litter functions under maintenace and ES6-incremental upgrade with "use strict", and then one will have to go back later and do more sweeping stoop-labor, picking up the redundant "use strict"; clutter and commoning it at a higher level via a module or a single "use strict" in an outer function or global code.

No one works for free. There has to be a motivation. You wrote of "carrots" and the ES6 features are indeed sweet. Your "use strict" fetish is still a stick, not a carrot. You're trying to get the horse (developer) to take a whack by feeding it carrots after. Sadistic! :-/

And if you're in a situation where you can't go strict, then you surely aren't ready to depend on transcompilation.

That's obviously not true. CoffeeScript does not generate strict code yet!

    In 10 years, you want everyone to use modules, but there'll still
    be top-level code, rapid prototyping, and so on. For such
    programs, you want everyone to write the old

    "use strict";


In 10 years loading code via script tags will be an abandoned practice, except for bootstrapping the module loader.

I will bet you real (beer) money you're wrong.

Look, "use strict" is the price that we have to pay for supporting a legacy language, in a legacy loading context, into perpetuity.

No, you assert this but it does not prove itself and it's not an axiom.

* "use strict" was a way to shoe-horn pragma syntax into ES5 (originally ES3.1) under "no new syntax" as a restriction.

* It bites back because old browsers see nothing, yet it makes runtime semantic changes in new browsers, but time will heal this wound.

* It's an eyesore, which I think is a non-trivial objection.

* It is easy to leave out and hard to find when checking whether code in the middle of a function nest is strict.

Yes, it's standard, but so what? Having one means toward an end (strict code) does not mean we can't have other, more usable means over time. And again we seem to agree about module making some module bodies (only the out of line ones? I disagree but at least we're talking!) strict by fiat.

It's not going to be free. Should we rather pay that balance by creating sloppy modes for all future ES versions? Is this the long term vision, then?

    ES3 < ES5 sloppy < ES6 sloppier < ES7 sloppiest
< ES5 strict < ES6 strict < ES7 strict

I'm not sure to whom you are addressing this rhetorical question. ES6 cannot mandate strict mode everywhere, so of course the default is sloppy. I'm the guy banging the drum for maximal (all new body-forms) strictness. That's the best we can do, for reasons recently rehashed in my reply to Claus Reinke on don't-break-the-web.

What comes after ES7 sloppiest mode?

You're ginning up a fake argument here: no one is adding *more* implicit conversion nonsense (well, almost -- destructuring does an implicit ToObject on the RHS and Andreas Rossberg disagrees; I will post a separate thread on this, it's worth revisiting). No one is pushing new with-like forms. No one is arguing for more arguments object usage, let alone more aliasing _a la_ arguments[0] and first-formal named x.

Since we cannot mandate strict mode, we'll always have some sloppiness. Many on TC39 hope to provide new and better vegetables and fruits to lead the horses away from the bad old forms, and module is certainly sweet. Why stop there?

Note also that "use strict" cannot be extended arbitrarily with incompatible further strictness that governs existing forms, or we'll have more broken content tested only in old or new browsers.

We want ES5 strict mode to stay the same, and ES6 by default to be non-strict. This means new syntax could implicitly opt into strictness (as I advocate where there are code bodies, i.e., functions), or developers could opt in by composing "use strict" or module with new syntax.

But nothing here says we add more slop.

To what extent does each new sloppy version have to drift from its strict counterpart? They cannot converge, so divergence is the only possibility.

No one is making new slop that a stricter ES6 strict must ban. If we were, you'd have a point.

(Forthcoming post on destructuring addresses the deeper issue Andreas raises: future-proofing for pattern matching, vs. being "consistent" with old slop.)

In this light, the least price for legacy support is to require "use strict" in legacy contexts (e.g. script tags).

You are asserting again. "least price" sounds measurable. If we count chars, or measure actual error rates forgetting to add "use strict", or quantify any other way, I'm confident that requiring "use strict"; is not the least-cost or lowest-price path.

New syntax bearing a code body can be strict, and 1JS starting with Dave's proposal (in full) has at least 'module' strict by fiat, for both inline and out of line bodies.

This is least-price in terms of reading and writing. You could argue it is higher cognitive load, since one must check for two things, a governing "use strict"; or a module ... { with closing } bracketing the code in question.

But again, "use strict" has worse usability and it's harder to find (no bracketing). In most editors one can set a mark, find the nearest preceding 'module', match the } for its opening {, and see by point vs. mark line number differences, coloring, or better visualizations that the code in question is bracketed.

If most modules are out of line, then it's even easier, and no ugly and easy-to-forget (or delete) "use strict"; at top is required.

I went through the inline-body module case because I think we will see inline bodies in the long run, a minority cohort for sure, but still useful. And I think the same delimiting/bracketing exercise should apply to classes at least (strict by default).

Granted, classes can be finer-grain and typically will be. Even moreso, generators and arrows. However, for new code strict should be the default, and usually it won't bite back. The biting has come when adding "use strict" at the "top" without carefully reviewing or rewriting all the code affected (and ignoring concatenation).

Pull off the band-aid, bite the bullet, etc. More harm is often done by taking the slow road. And ES6, with it's substantial syntax improvements, is the best opportunity we'll have for getting it over with.

This is all kind of circular. You assert "use strict" is least-price and then make it the only way to get more strict code.

If by "pull off the band-aid" you mean get more strict code in the future than in the past, faster (more and faster over any measurable adoption interval), then making bodies strict by fiat wins.

OK - so why not make all new code-bearing bodies implicitly strict then?

(Finally! :-P)

Won't that buy us more strict mode usage? Well, sure, but the price is added complexity.

Complexity is not a unitary evil. It exists in your proposal too, not just due to usability and aesthetic problems of "use strict", but also in the friction in favor of sloppy code you are creating (those users, the ones I set aside temporarily in my last message, who would use ES6 but can't yet turn on strict mode at a high level).

Is the big fat future, with lots of modules, classes, arrows, and some generators, really more complex on balance, if those forms are strict? I don't think so.

It sounds simple enough, but when we start digging into the details, little problems emerge (like "let").

No, you are mixing topics. 'let' is a problem for new syntax as its own opt-in (so was 'module' but we did the obvious contextual thing).

'let' is not a problem for new-bodies-are-strict-by-fiat.

Please keep these two issues separate.

It's already complex enough to support both strict and sloppy modes, why compound that complexity by extending the reach of sloppy mode?

I'm not, I'm extending strict by design into new bodies.

I think that pretty much sums up the position, and the horse may be quite beaten at this point. What do you think?

I think the two issues I argue should be kept separate (new bodies are strict vs. new syntax is its own opt-in) are connected in your mind by "complexity".

*If* we keep the ability to make 'let' new syntax be its own opt-in (which again, we think we can keep via some lookahead restrictions and left context, similar to what we do elsewhere in ES1-5 and ES6 for 'module'), then there's no problem. But you could be right and we'll end up makin 'let' available only in strict mode (enabled by whatever means we choose).

Function-in-block faces a rougher road, and looks likely to precede 'let' into strict-only status -- but Mark at least wants to evangelize, so we don't have two f-i-b semantics (only one of them specified). We knew it might not be possible to change f-i-b semantics in all modes to match ES6, in particular to scope the hoisted binding to the enclosing block. This may happen, looks likelier, but not a done deal either.

Your complexity argument is that by putting all new syntax (save 'module') under a required "use strict" (or out-of-line module?), developers don't have to face certain complexity. I argue, to the contrary, that they face as much or worse. They have to:

* find the governing "use strict" for a given piece of code in a function nest;

* worry about module inline-to-out-of-line refactoring breaking pre-strict code that was put in the inline module in a prior refactoring step;

* keep using 'var' in code when in doubt about strictness, retarding 'let' adoption.

* face old f-i-b code that has different semantics from new f-i-b, but this one can't be solved other than by the *end* of strictness, so it is not an argument for or against a particular *means* of enabling strict mode.

The last bullet is a hard case that won't go away in any scenario, in the worst case where we can't evangelize old content to new semantincs. Yet it doesn't crack your perfect dodecahedron vs. my different (and more usable) smooth-hand-fitted shape :-P. Why not?

/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to