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'?
Easy: module is still a first
The only place 'let' is contextually reserved in the quasi-consensus from
the last TC39 meeting is at the start of a statement, when followed by an
identifier, '{', or '['.
Right - which makes let a second class identifier (sorry,
made-up-term), since it can't be used in let[x] = y. I
shed
This is a bit long - bear with me...
First, let me make one more argument as to why new syntax, just use it
won't work:
(a) In ES6, let is the preferred way to declare variables. Let's not be
relativistic to the point of goo here. Block-scoped variables are
better. As such, let is of central
I gotta say, I'm in agreement with Mark (and even Andreas) here. 1JS,
under all modes just isn't going to work (let[x] = y proves that). And
keeping track of what's allowed under which mode (and why) could get
complicated and difficult to explain.
But what about this?
One JS,
Under strict
The more I think about this, the more convinced I get that all new syntax
and breaking changes (where possible) should be strict-mode only. In
retrospect, `let[x] = y;` changed everything. Here's why I think 1JS
under strict is the best solution:
- How exactly would one teach that classes,
Ease of teaching != successfully imparted knowledge at scale. Sorry, but
it's true. People don't use use strict; at top level enough, and teaching
them all will take time. Even then, because of the Law of Least Effort,
it'll be left out.
This is the major objection some of us keep raising,
1) All new syntax and breaking changes (where possible) are strict-mode
only.
2) Modules and only modules are implicitly strict.
(2) is not what (1) says, ignoring the mysterious (where possible)
loophole.
You're really sharp! Notice that I didn't specify in or out-of-line
modules
So I don't see the argument against implicit strict as overriding.
The main argument against implicit strict, peppered across new syntax, is
increased complexity for little gain. In other words, bloat. If you want
implicit strict, then do it for module bodies only (in or out-of-line).
What about node code?
Well, node modules are not ES6 modules. They are functions with an
implicit head and braces. So implicit strict mode, applied to ES6 modules,
would not apply to them.
{ Kevin }
___
es-discuss mailing list
Sorry, I should have expanded further - that was my point. Node is a case
where I can see classes being used without modules. I imagine native class
support will hit v8 soon enough, and I could see people start using them
without trying to switch to ES6 modules.
Ah - true. They can put a
That implicit head and braces are in the library, though; so if node wanted
(and it would be possible somehow), it could replace it with module. Still
don't know if exporting / reentrant require could be handled without much
fuss.
Possible, but not really clean or (I think) satisfactory, due
module foo {
export let state = 5;
export function modifyState() {
state = 10;
};
}
import { state, modifyState } from foo;
assert(state === 5);
modifyState();
assert(state === 10);
That's it.
This is, to me as an ES5 programmer, very weird. There is *no other
situation in
So I fully agree with all of Andreas's points. Another one is that I've
been thinking we should add getter/setter exports to make it possible to
create lazily initialized exports:
let cell;
export get foo() {
if (!cell)
cell = initialize();
return
I guess we'll see soon enough, but I think there's still going to be a big
battle between ES6 modules and node modules and amd/requireJS. Any early
adopter types have already probably invested in something, and because the
porting isn't always straightforward, I think many will stick with what
+1 for adding getter/setter exports to make it possible to create lazily
initialized exports. This could be very useful for frameworks to keep
footprint lower without causing unintuitive designs.
No - we need to keep features out of the module system. Abstractions
should be created with the
Just to finalize this thread, I updated the gist based on comments from
Andreas:
https://gist.github.com/4382710
It includes syntax for proper inline modules, and an extension syntax for
pre-loading (aka concatenating). It also brings the syntax for module
aliasing closer to the previous
However, I agree that the destructuring syntax for module imports may not
be the clearest choice in terms of raising the right expectations. (As we
have discovered already, it has other issues, namely people confusing the
direction of renaming.) Maybe it is a bit too clever, and considering
The question really is, why have sloppy-mode classes at all? Who wants or
needs them?
Well, no one, really. But we shouldn't want big invisible switches or any
new pragma-haunts either.
You've said that my predictions are wildly optimistic, and I'm going to
have to push back.
Let me, like
There's no invisible switch. You are assuming something not axiomatic:
that new syntax head-forms other than module must inherit sloppy from outer
code. That does not follow without more argumentation.
I guess I'm saying that anything other than inheritance, without the
pragma, is an
1. Except for module.
Right.
2. Non-locality of use strict in the medium-to-large makes for an
effectively invisible, or at least hard to see as in effect, switch.
Mmmm.. maybe.
So are you in favor of class body as strict by default?
You mean as always strict? I wasn't when I wrote
Since any new code will likely be written as a module (even in the
near-term, transpiled back to ES5), this would be the ideal scenario.
Which this do you mean? modules (in or out of line) implying strict mode
can target ES5 strict, no problem.
This meaning all module code (in or
First, maybe the 1JS term is a bit confusing and should be retired.
I think a few simple rules are in order:
1) No opt-in required for new syntax, except:
2) No breaking changes for sloppy mode.
3) No implicit opt-in to strict mode.
Everyone agrees on rule #1. Rule #2 implies no let
You're not in marketing, are you :-P.
No - and if I had any marketing sense I'd have a much better day job : )
Indeed, it goes against Dave's original proposal that module opt into
strict mode, which avoids some problems with sloppy mode in modules, e.g.
implicitly created globals by
It does not even contain the word strict. IIRC (and I asked about this
at the last TC39 meeting and got verbal confirmation), the idea of module
{...} implying strict mode was latent, or intended. I'm not sure about out
of line modules.
At this point, best thing is to summon Dave.
Since
The latter scenario isn't important for the 'module exports a single
function which is identified with the module' case, but it is
important for gradual migration to ES6. It's much easier to convert an
ES5 library that attaches a single value to the global object to a
single-export module by
I've worked up a concrete variation on the modules syntax:
https://gist.github.com/4337062
I believe that it presents a clean, simple model and coding experience.
Comments welcome!
- Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
What you _do_ want to have IMO, though, is module aliases
module Short = Long.Qualified.Module.Name
I agree.
OTOH, one more other feature I could consider dropping for the time being
is the ability to export from a ModuleSpecifier. I'm not convinced that
this is a common enough use
Assigning a single exports also nudges people to make small modules
that do one thing.
A Node-ism for which the benefit is not yet proven : )
It is a design aesthetic that has been established in the JS
community, both in node and in AMD modules, in real code used by many
people. So
In summary, I do not believe there is a technical issue with export
assignment and backcompat, which was the what started this thread.
Why not? I've attempted to show that it's not possible to correctly use
this feature for backward compatibility without parsing the code first.
Pre-parsing
At first glance, it seems like anonymous exports might provide a way for
pre-ES6 (read: Node) modules and ES6 modules to coexist. After all:
exports = function A() {};
just looks so much like:
module.exports = function A() {};
But is that the case? Does this oddball syntax actually
I consider such second-guessing of user intention, which can lead one
construct to mean completely different things, harmful. It makes code
less readable and more brittle. And again, it's a semantic hack,
making the language more complex. I just don't see why it would be
worth it, especially
Since it is just sugar, and supposed to be equivalent to the
expansion, you (fortunately) would get an error (statically).
OK, then suppose we have these two separate forms:
import x from url; // Bind x to the anonymous export, if defined,
otherwise error
and
import module x from
So if you didn't set the anonymous binding in some module x.js, what
would this do:
import x from x.js;
Would x be bound to the module instance or would we get a binding error?
For module naming, we'd need to have a different syntax. In earlier
versions of the proposal that was
module
Summaries with comments:
1) export ExportSpecifierSet (, ExportSpecifierSet)* ;
Brendan pointed out that other binding forms allow lists (including the
import form), so why not this one? I actually didn't realize that lists
are allowed with import:
ImportDeclaration ::= import
The downside is that it introduces a severe anomaly into the module
semantics (a module which actually has no instance). I could live with
this feature if we were to find a way to explain it in terms of simple
syntactic sugar on both the import and export side, but screwing and
complicating
Note, however, that you still assume some hack in the semantics with
the if it exists part. To avoid that, you need to divorce the import
syntax from the naming-an-external-module syntax -- which I'd actually
prefer anyway, and which was the case in the previous version of the
proposal.
Dart has a cascade operator (..) [1]. That's the Right Way to do chaining.
We should watch how it goes in Dart before prematurely committing to this
iffy simulation of cascading at the API level.
- Kevin
[1]
I've had a look at the changes to the modules wiki page [1]. I'm liking
the syntax changes quite a lot actually, but I have a couple of comments:
1) export ExportSpecifierSet (, ExportSpecifierSet)* ;
This rule seems too permissive. It allows strange combinations like:
export x, { y:
=== @names ===
I think punting on @name syntax until ES7 is a wise move. I would like to
sneak in a word of clarification on my modular @name proposal, though. In
my proposal, @names are not implicitly declared variables. They are
namespaced identifiers, where the namespace container is the
1JS wants new syntax to be its own opt-in.
Right - except of course `let[i] = j;` isn't new syntax. In non-strict,
`let` is either an identifier, or it isn't. If it's an identifier, then
let it be a full-fledged identifier, not some half-man, half-beast. I
think it's best to avoid situations
Of course, you cited only one sentence I wrote and cut the rest where I
adverted to the problem.
Sorry - I get creative with my cuts sometimes : )
But is it a real problem?
Probably not, but my POV is that if let is an identifier (and in non-strict
mode, it will be), then let it have all
I would like to defend Dave against Kevin's wildly.
Yeah - it *was* a little inflammatory. Sorry, Dave. I think you rock, of
course : )
That the default loader knows about pathnames and .js is a good thing in
my view. You want something else, write another loader.
Actually, I feel like
It's a bit unclear to me how arrow functions react to semicolons, for
example:
var a = (c) = {
var b = 2;
b * c;
}
a(4);
Hmmm... I was under the impression that arrow functions with normal
function bodies do *not* implicitly return anything. Maybe I need to
adjust my spec goggles,
Dave Herman proposed as part of 1JS that module imply strict mode, so let
is reserved in module. So that helps.
Sure, for inline modules. But are externally loaded modules strict as
well? I think they should be...
1. 'let' only in strict code including modules per 1JS as originally
Another experiment would tell us more...and as Peter points out, there are
people who like to put their declarator keyword on a separate line.
Mmm... I think a [no LineTerm] restriction is going to bite too hard in
this case. If let in non-strict mode were a context-sensitive keyword,
with a
So the only code that would break would be expression statements
consisting of the single identifier let, followed by an ASI'd newline.
Is that right?
To reply to myself, there's also this:
var let = [], num = 0;
let[num] = f();
Hmmm
I suppose a radical but safe solution
var let = function() {};
let();
If let is a contextual keyword (in non-strict mode of course), then we can
look ahead to the token after `let` to validate it. An open paren cannot
follow a let *keyword*, so therefore it must be an identifier.
var let = { it: be };
let.it //
If the second argument is optional, it's possible to have both one-arg and
two-arg styles in the same API.
What do people think about this idea?
Maybe - minimalism served the class proposal quite well. It might be a
good strategy here, too.
Here's what I'm thinking:
// Creates a new
Why go purposefully against the existing terminology of the JavaScript
ecosystem? Just say “deferred” where you have “promise” and “promise” where
you have “future” and you avoid needless confusion and conflict.
I prefer to find the optimal solution first and then consider migration
costs
I think you meant optimally colored bikeshed, but OK.
Ouch : )
Names are important. Especially when it comes to something as potentially
confusing as promises and futures.
- Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
I personally think Scala made a good choice, because most of the time all
we are concerned with is the future. And we can talk about futures
independently from invoking the promise analogy. I think the promise
analogy is great, but in my opinion it can be a little bit tricky for
people to pick
Is the following a counter-example?
On Fri, Nov 9, 2012 at 8:33 AM, Mark S. Miller erig...@google.com wrote:
Hi David, thanks for your thoughtful post. I've always used the two-arg
form of .then[1], but your post makes a strong case for more often using
separate one-arg .then and .fail
return AFS.stat(path)
.fail(error = null) // map failure to success condition
.then(stat =
if (!stat)// Path doesn't exist - create the directory
return AFS.mkdir(path);
else if (stat.isDirectory())// done already
return 'nothing to do';
We have found this to be more expressive as well. Especially in ES5
environments, where we can use Q's alias of `catch` instead of `fail`:
p1.then(val = doStuff)
.catch(err = console.error(err));
Nice: +1
However, I see a lot of value in when as a word still. Then makes
sense when
p1.then(val = doStuff)
.catch(err = console.error(err));
Nice: +1
On further thought, I'm not so sure. Consider this code, which creates a
directory if it doesn't already exist and then logs done.
return AFS.stat(path).then(stat = {
if (!stat.isDirectory())
Hi all,
I thought it might be helpful to compile a list of terms that different
libraries and languages are using for promises.
In general, we need two terms: one to describe an object which can set the
state of the eventual, and one to describe an object which can only read
the eventual.
This
In other words, futures provide synchronisation, while promises
provide resolution.
This is exactly the API that Q (and it's derivatives) use, although the
nomenclature is different. In Q, the future is called a promise, and the
promise is what you get from calling defer():
let {
Any other reasons for why they are discouraged?
This footgun:
function MyClass() {
this.value = 1; // OK
this.list.push(0); // Modifying the list for every instance -
probably not intended.
}
MyClass.prototype.value = 0;
MyClass.prototype.list = [];
- Kevin
Just speaking as a spec reader, I say go for it.
- Kevin
On Fri, Nov 2, 2012 at 6:08 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:
In both ES5 and ES6 (so far) we have generally tried to maintain the
section structure of the previous editions. Occasionally we have had to do
some minor
I might steal always bet on JS, or maybe I'll emphasize the way we can
use these features today (SpiderMonkey, Chrome Embedded Frame or Node.js
apps with flags, Traceur and other transpilers for the non-magic...). Still
thinking on it, and of course toeing the sleep-dep/productivity line.
I see two coherent alternatives:
(a) execute inline modules by need (i.e., on first import) rather than
eagerly
(b) execute external modules transactionally, trying to order them by
dependency so that imported modules have fully initialized before the code
that depends on them runs
I
Browsers can load from ZIP files, some even supported the .jar variant and
http://some.site.com/big.jar!**memberhttp://some.site.com/big.jar!membernotation
(not sure what's still working there). But this is again
multiplying risks. Will developers all ZIP this way, instead of using TE
Do we log you need me only when f is called for the first time?
Sorry - that makes no sense. What I meant was:
module A {
console.log(you need me);
export var x = x;
}
export function f() {
console.log(A.x);
}
Do we log you need me only when f is called for
Just to be sure... Does a get printed only the first time the module A is
imported somewhere, or every time?
Only the first time. But the question here is about nested/inline modules.
Patrick, it must be the other way. Here's why:
module A {
export function f() {
1. The one-class-per-file pattern is near universal. When there is more
than one class, they tend to be in minor supporting roles (like
exception-type subclasses or simple data structures).
2. Adding private, protected, etc. declarations to classes adds a good deal
of baggage to the syntax that
What do you think about the typo problem? Not a major issue?
It's javascript, so I guess I'm used to getting pinched every now and then
by a little property misspelling. It's never caused me to miss
C#/C++/Java/etc. And it all washes out with proper testing.
It seems orthogonal to me
Hi all,
With modules, we're going to see code broken up into more and smaller
files, which directly opposes the desire to minimize the number of HTTP
round-trips. On solution is concatenation, but if I'm not mistaken there
are potential order-of-execution issues with that approach. Another
I believe that concatenation of modules ought to work fine as an
approach for minimization of requests, because modules are executed
when imported.
OK, so:
module A {
console.log(a);
export var x;
}
console.log($);
import x from A;
Does this print:
$
a
For the case of importing 37 at-names, I would expect that * imports
would take care of it:
import * from ModuleDefining37NameInterface;
Oh, come on!
The problem isn't importing the names. The problem lies in having to
maintain a nightmarishly long set of declarations which are
This looks like the sort of thing that will get labeled uselessly
unreliable, then again I was in favor of making length equal the number of
formal parameters—rest included.
Right - the simpler the rule, the better for this kind of thing. I
wouldn't include rest, though, because it's
Anything but optional and rest (as speced) is the simplest rule I can
think of, except everything including rest, but no one wants that.
But the current spec does not say that. It says stop counting at the first
default, which doesn't really tell anyone anything useful about the
function's
Have you found the actual usage of length in node libraries to enforce
this sort of signature testing? I was poking around and haven't found it.
Note that the http://expressjs.com/guide.html#error-handling only says
must be defined with an arity of 4, that is the signature (err, req,
res,
Given that you need to import symbols, I prefer explicit declarations
(which will also be used for exporting).
Thanks for your feedback!
The problem with explicit declarations is that it's going to be burdensome,
for no apparent gain. Consider: I have a real-world class with 37
internal
You seem to be under the mistaken impression that ES6 allows non-defaulted
arguments after default ones. This is not the case. See
https://mail.mozilla.org/pipermail/es-discuss/2012-October/025704.html
for a (very) recent discussion of this.
I don't think that is true. See Allen's
Also, I see no evidence in the latest draft that defaults after a
non-default is a static error. Please correct me if I'm wrong, of course!
Sorry, meant non-defaults after a default in the above.
Need...more...coffeee.
Kevin
___
es-discuss mailing
Also, I should mention a couple of things:
1. This design essentially paves the cowpath trod with underscore-prefixed
property names, adding the desired property of conflict elimination.
2. If System is a built-in *module instance*, and the @iterator symbol
is defined internally within that
Yes, although I don't take the private, who needs it? attitude as easily
as you do. Not saying it's wrong, but I'm not 100% convinced yet.
In a way I'm posing a challenge - I think it will be an interesting debate
to have.
Doesn't this have the same problem you were arguing against in your
express for node already does this, for error handlers:
http://expressjs.com/guide.html#error-handling
express is very popular; #4 on Most Depended Upon packages; #1 on Most
Starred at npm:
This is helpful. So, judgement aside, we can say there is a certain level
of usage of
And specifically not stopping counting at the first parameter with a
default value, right?
Yep. Would it also work for this use case to stop counting at the first
parameter with no default value, after which there are only defaults?
function f(a, b = 2, c, d = 4, ...rest) {}
f.length
Hi all,
ES6 is shaping up quite nicely. The last big area which I feel is still
quite foggy is syntactic support for symbolic property names, which Allen
has addressed with his at-names proposal. Perhaps syntax won't make it
into ES6 regardless of the work we do, but I think the symbol story
I notice that the current draft spec says:
The ExpectedArgumentCount of a FormalParameterList is the
number of FormalParameters to the left of either the rest parameter
or the first FormalParameter with an Initialiser.
This aligns ExpectedArgumentCount with built-in functions like
We've discussed this extensively before and there doesn't seem to be many
plausible use cases for the function length property.
Here's the only use case that I've encountered (admittedly not particularly
strong): Overriding the behavior of a function/method based on the
signature of an input
Also, if concise methods introduce a binding, then there's the hazard that
an outer binding of the same name will get unintentionally shadowed.
Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
function f(x1, ~~~, xN) {
if (x1 === undefined) x1 = e1;
~~~
if (xN === undefined) xN = eN;
return (function(x1, ~~~ xN) { body }).apply(this, arguments);
}
Effectively sibling scopes, with a copy mechanism from the defaults scope
to the body scope. That's what I was going
It addresses a common pattern today, that looks like:
function Led( opts ) {
if ( !(this instanceof Led) ) {
return new Led( opts );
}
// ...
}
Yes - I explored this idea back when we were discussing classes several
months ago. The thing that you have to consider is that
The issue, is providing access to an already created symbol across such
boundaries. As I have pointed out in other messages, this isn't a problem
that it unique to symbols. It is isomorphic with use cases for sharing any
kind of object across such boundaries.
I disagree. The only reason
And the strings supplied to Symbol.for/from form a single namespace across
the entire executing environment?
Across the observably connected realms. Independent window/frame graphs
that are disconnected, no need or way to tell.
Ah yes.
Sounds good. As an aside, does the symbol in this
Indeed, which is why I'm not sure I understand what this idea is
trying to achieve. Is it more than just an ad hoc way to introduce a
second namespace?
Presumably, so that such a namespace can be used with a
property-name-substitution syntax.
A question: is
var symbol = new
- Symbols, even when not used for encapsulated abstractions, are
great for avoiding the possibility of collision in the global string
namespace
- So, we (tc39) decided to use them for to replace the property name
currently called iterator in Spidermonkey.
- Currently, iterator works
Kevin should weigh in, since he is thread-starter.
I'm blushing...
I'd like to back up a bit. Just to be clear, any two occurrences of:
Symbol.from(abcdefg); // or Symbol.for...
from any module, in any global context, will result in the same symbol?
Kevin
Yes, that's the intent.
And the strings supplied to Symbol.for/from form a single namespace across
the entire executing environment?
So if an author wanted to guarantee no conflicts, they would need to use a
suitable globally unique string (like a uuid or reverse DNS name, or
something else
One of the main use cases for symbols is for defining object protocols
that don't suffer from property name conflicts. The recently discussed
`iterator` and `toStringTag` method names fall into this category. The
idea is that we can implement the protocol by defining methods using
symbols, and
private @FooBrand;
class Foo {
constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
}
}
Foo.isFoo = function (obj) {return !!obj.@FooBrand};
Using this strategy, will isFoo not fail, if the specified object came from
a
On the other hand, if you have many instances that need to be branded I
suspect that the distributed symbol based technique is going to have a
better performance profile than the WeakMaps.
Is this true? Are there performance caveats that come with current
WeakMap implementations?
Kevin
(One-handed Luke Skywalker voice:) NOo
: ) Another perfect response!
Kevin
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
I think Allen is absolutely right that the magic incest of current
built-ins is not going to scale, is semantically questionable, and
should best be abandoned.
: ) magic incest. This is pretty much a perfect response.
Kevin
___
es-discuss mailing
1) Use Variant B for external modules
2) ExportDeclaration ::= export ExportSpecifierSet ;
3) ExportSpecifierSet ::= * ([noNewlineBefore] from ModuleSpecifier)?
___
es-discuss mailing list
es-discuss@mozilla.org
1) Use Variant B for external modules
2) ExportDeclaration ::= export ExportSpecifierSet ;
3) ExportSpecifierSet ::= * ([noNewlineBefore] from ModuleSpecifier)?
Blerg - meant to Save Draft and submit this for discussion at a later
date. Apologies.
Kevin
Looking at the July 8 Draft, I notice that arrow functions are produced by
AssignmentExpression, not PrimaryExpression (as function expressions are).
Why is that? Is it to limit the operators that can be applied to them?
When descent parsing, we have to drill down into primary expression to
Never mind - it's to prevent grammatical ambiguity in the concise form.
Sorry for the noise.
Kevin
On Mon, Sep 24, 2012 at 8:55 AM, Kevin Smith khs4...@gmail.com wrote:
Looking at the July 8 Draft, I notice that arrow functions are produced by
AssignmentExpression, not PrimaryExpression
701 - 800 of 952 matches
Mail list logo