Re: First crack at a Streams proposal

2013-04-22 Thread Isaac Schlueter
> That request is nearly always followed with an (explicit or implied)
> "And if it can be, why should we do it? Leave it to libraries!"
> statement.  If you did not intend this, then I apologize.

Well, actually, I think that we *should* do it with libraries for a
bit, because I have come to believe from repeated experience that this
is the only reliable way to evaluate patterns, and that forcing
acceptance of a specification in advance of trials leads to a lot of
error.  Again, qv promises, map/set, etc.  That's how it's done
because it works.


> You need Object.observe to do reactive values as an event stream.  You
> can do event streams (turning DOM Events into a stream) with today's
> JS.

Are you proposing reactive values as an event stream?  It seemed like
your proposal was mostly pretty simple interfaces.


> Apologies for the mismatch in expectations.  I recognize that
> reference implementations are more *customary* when proposing things
> in JS that don't depend on new primitives.  Instead, I provided a spec
> that sketched out appropriate details (and can be filled in further as
> necessary).  For the purpose of discussion of the idea, the two should
> be roughly equivalent.

I disagree.  They're not equivalent at all.  Not even roughly, not
even close.  One can be tested, reviewed, and subjected to experiments
in the real world.  The other is imaginary.


> Again, I'm aware that JS proposals often come with a reference
> implementation, or at least a sketch of one.  That's not strictly
> necessary to review and talk about a proposal, however.

To do so responsibly, I believe that it is.


> If you think
> that you are unable to even discuss the proposal without such a
> reference implementation, then I'm sorry that we will have to lose
> your voice until I have the time and engery to provide such.

Actually, I strongly doubt *anyone* is able to adequately discuss the
pros and cons of a proposal like this without an implementation.

I don't have anything else to contribute until there is a reference
implementation.  I'm not super motivated to write it myself, but I'd
be happy to test it out, or consult about any sticky issues you run
into, etc.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: First crack at a Streams proposal

2013-04-22 Thread Isaac Schlueter
On Sat, Apr 20, 2013 at 12:47 PM, Tab Atkins Jr.  wrote:
> On Sat, Apr 20, 2013 at 9:19 AM, Isaac Schlueter  wrote:
>> I'm not seeing what in this proposal can't be implemented in
>> JavaScript as it is today.  Is there an implementation of this
>> somewhere?  Are there any programs that use these streams?
>
> This is a fully-general counter-argument against literally everything
> that doesn't require new primitives, and so is useless as an actual
> argument.

It's not fully-general counter-argument, because it's not an argument.
 It's a request for more information.  Until I have that information,
I don't have enough information to form a reasonable opinion.

I read your proposal.  It appears to be something that is
implementable with today's current JavaScript.  Am I mistaken?  If so,
how so?  (Ie, what new language semantics or primitives are required?)

If I'm not mistaken, then where's the reference implementation?  I
don't even see example code.  I figured that I must be missing
something.


You're wrong about what it would damn, in every case.

>  It would damn Promises/Futures

Promises had many, many iterations in working code long before a
specification was ever proposed.

> Sets, Maps

Both required new language semantics.  But there WERE reference
implementations of both, long before either of those reached a spec.

> and a number of other new things.

Please be more specific.  There are many numbers.  Don't allude to the
vastness of your point, just make it, or don't.

Search npm and github before making claims about what things would be
damned by the request for a reference implementation in advance of a
specification.


> Please note that the proposal topping this thread is already
> long-obsolete.

Then please update the thread with the updated proposal, and
preferably a link to the github account with the reference
implementation, if such a thing exists.

If such a thing does not exist, please explain why it is not feasible
to write an implementation of this with today's language semantics.

If I seem a bit impatient, it is because I am eager to have an opinion
about this idea of yours, but I find myself incapable of responsibly
having an opinion without seeing it in action.

As you say, the concept of event streams appears in many libraries.  I
work daily with Node.js, which is full of event emitters and binary
data streams.  You mentioned that it would be easy to implement binary
streams on top of your streams idea.  I'd like to see that.  I know
from firsthand experience that streams can be surprisingly hard to get
right.  In my opinion, if you can't easily implement TCP, TLS, and
Zlib on a stream implementation, then you haven't gotten it right.

So, the fact that an implementation has not yet been shown seems quite
strange to me, because that would be the *first* thing that I'd expect
anyone would want to see, and it seems like it'd only take a few
hundred lines of code to do.  I say that because other "streaming" FRP
pattern libraries have been implemented in just a few hundred lines.
Look at the work of Dominic Tarr (dominictarr) or Irakli Gozalishvili
(gozala) on npm and github.

Until there is an implementation, I don't really see what there is to
talk about.  As I said, this is not a counter-argument, because as far
as I'm concerned, there's nothing to even argue about!
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: First crack at a Streams proposal

2013-04-20 Thread Isaac Schlueter
I'm not seeing what in this proposal can't be implemented in
JavaScript as it is today.  Is there an implementation of this
somewhere?  Are there any programs that use these streams?

On Mon, Apr 15, 2013 at 9:19 PM, Tab Atkins Jr.  wrote:
> On Mon, Apr 15, 2013 at 5:26 PM, Kevin Gadd  wrote:
>> OK, it sounds like this is sort of a 'lossy' stream concept, then, in that
>> if you fail to call next() early enough, you can miss data from the stream?
>> I can see how that would be acceptable for certain use cases. To me though,
>> this limits use of the primitive.
>>
>> Here's a hypothetical. I'm building an instant messaging webapp - think
>> google talk - and I want a 'stream' that represents the status of my online
>> buddies. So each time someone goes online/offline, that would come through
>> the stream.
>>
>> It sounds like with this design, were I to use next() to pull data out of
>> the stream, any online status changes that have occurred before I called
>> next() are lost forever, because at any given time all calls to next()
>> return a future for the 'next update'. This means that if the portion of my
>> service responsible from the contact list starts later than the actual
>> network backend, it can miss status changes and end up with a partial
>> picture of the state. Maybe that's ok.
>
> Yes, my current model doesn't buffer changes before the first
> listener.  This is the correct behavior for most DOM cases, but I see
> how for a lot of other cases it's less good.  By default, you might
> want to have that buffer, so the first consumer gets to see all the
> history, at least.  (If you want multiple consumers to all get the
> history, you should opt into that explicitly via some slightly less
> convenient API, as it means infinite buffering.)
>
>> Similarly, it sounds like given this model if I have 3 consumers, and they
>> all call next() once to get values, they have to be absolutely certain to
>> call next() again *as soon as* the Future from the previous next() gets
>> data. If they do the 'right thing' that you normally do in Future-oriented
>> scheduling, where a future being activated results in a task being scheduled
>> to do work, it's possible to miss data, given a flow like this:
>
> `next` is for when you just care about the very next time something
> happens.  If you care about all the events that come out, use `listen`
> instead.
>
> It looks like many existing APIs use `next` for more pull-based
> purposes, where the stream will buffer data until someone pulls it out
> with `next`.  My current API is explicitly *not* pull-based, but it's
> easy to imagine a subclass that is.
>
>> Another question: Given this sort of 'synchronized' update model, what
>> happens if two consumers both cause data to be pushed into the stream? There
>> are two values to send out, but next() only has room for one value. Does the
>> second value get thrown away? Does an exception get raised by the second
>> push? I don't know how you can ensure that all the consumers will see the
>> second value.
>
> Same thing - consumers should be using `listen` if they want all the
> data.  That's the "default" way to interact with a stream in my
> proposal.
>
>> I think I will have to echo others' thoughts here that this really doesn't
>> seem like a 'Stream' API. It does not match the semantics of any Stream
>> primitive/concept I have ever encountered in an API.
>
> Yes, the name seems to be confusing people.  On the other hand, I find
> a lot of the other existing names hopelessly opaque or awkward -
> Signal doesn't mean much to me, and Observable is too abstract.
> Stream is just the right kind of name to convey "a stream of updates",
> but unfortunately the name is co-opted by binary IO streams. :/
>
> ~TJ
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: `free` operator

2012-10-26 Thread Isaac Schlueter
So, yes, you can certainly use debugging tools to find which objects
are leaking.  But, there are times when you have a program where
something is leaking, and you read through the code, and see that
there is no possible way that it could be leaking (but it is, as
reality sometimes stubbornly refuses to be told what to do.)

Use-after-free bugs are not great, but they are relatively easy to
track down.  And, in general, a program that crashes when it does
something wrong, is handling it exactly right.  Slowly leaking memory
is much harder to diagnose, and usually much harder to correct.

We've got some band-aids in place in the node http.js file to prevent
parser leaks.  A more forcible free() method would have made it much
easier.  The long-term solution is to rewrite the program so that it's
not so badly architected, but as is so often the case, we didn't
realize the architectural mistakes until we had made them, and fixing
them is quite costly.  (Node's http implementation will get a massive
refactor in 0.12.)

Yehuda's "action at a distance" complaint is definitely a valid
concern.  However, note that an object can't be freed unless you have
a reference to the object.  Thus, any code that would set my reference
to undefined could only do so if it was also capable of mutating the
object in any other way (adding/removing properties, etc.)

So, we already have this:

function () {
// acquire a ref from some external code
// no way of knowing what else is sharing this object
var x = func()
x.foo = 'bar'
// other code...
doAnotherThing()
// not guaranteed!
assert(x.foo === 'bar')
}

Whenever you have a reference to an object that is shared with some
other code, there's the potential for action at a distance.  The
proposal here is to make that action a bit more powerful.

I don't agree that it's necessarily a problem in production.  We free
objects in other languages all the time.


On Fri, Oct 26, 2012 at 5:11 PM, Patrick Mueller  wrote:
> On Fri, Oct 26, 2012 at 11:51 AM, John J Barton
>  wrote:
>>
>> Debugging tools lag other tools in part because test-cases or
>> use-models are hard not readily available.
>
>
> But the only debugging tools we really have are proprietary low-level APIs
> (eg, V8 debug stuff), and some existing debug ui frameworks (eg, Web
> Inspector).  The barrier is so, so high for this stuff.  Compared to a
> number of other environments where the barrier is not so high.  Eg, in C, if
> you're debugging memory issues, switching to using a debug malloc library
> isn't a huge barrier.
>
> It would be nice to lower the barrier, expose some "debug" stuff in JS.
> Implying that I want "debug APIs" available in JS, and I want to write my
> debug helpers in JS.
>
> V8's --expose-debug-as (or whatever) trick is a step in the right direction.
> It would be nice to have some commonality here, so I don't have to write one
> set of debug helpers for V8, another for JSC, another for *Monkey, etc.
>
>>
>> The js-tools group would be ideal for more discussions of these
>> issues: https://groups.google.com/forum/?fromgroups=#!forum/js-tools
>
>
> Ah, nice.  I'll stop pestering here, and start pestering there.  :-)
>
> --
> Patrick Mueller
> http://muellerware.org
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: `free` operator

2012-10-25 Thread Isaac Schlueter
On Fri, Oct 26, 2012 at 1:35 AM, Shawn Steele
 wrote:
> I sort of have a fundamental problem with the solution.  Eg:  If it were 
> actually unused, it'd be GC'd.  Since it isn't GC'd, something must be 
> holding a reference to it.  So if you force it to be gone, or clear all the 
> properties, or whatever, seems to me that then you'd just start throwing 
> random errors in the code that tried to use the "freed" object?  That might 
> be even harder to track down.

On the contrary, "TypeError: Cannot read property 'prop' of
undefined", with a stack trace, is WAY easier to track down than "The
RSS on my server gradually rises, until the operating system kills it,
which happens about every 4 hours."

Fast failure is not as good as success, but it's better than anything else.


> On Thu, Oct 25, 2012 at 4:16 PM, Isaac Schlueter  wrote:
>> It'd be really nice if JS had a way to explicitly delete an object.
>
> I guess you mean ... a way to set all the refs to a object to undefined.

Yes, exactly.


On Fri, Oct 26, 2012 at 1:20 AM, John J Barton
 wrote:
>> var obj = {}
>> var foo = { ref: obj }
>
> I assume that in your real life, you don't know 'foo' but somehow you
> know that foo.ref is never used?

Well, you know that IF foo.ref is used, it's an error, and ought to
throw.  Also, it's quite easy to check if the property exists, and set
it to a new object if so.  It's common to have things like:

if (!this._parser) {
  this._parser = new ParserThingie();
}

In this example, imagine that parsers are expensive to create.  So, we
try to reuse them (danger!), and over time, our program grows until we
have some code paths where the parsers are not getting all of their
data removed properly.  If the parser has a ref to an object that has
a reference to some other thing, etc., then you've got a memory leak.

This exact situation happened in Node's HTTP library a few months ago,
and was very tedious to fix.  We quite easily identified one of the
things in the chain, and that it must have been linked in some way to
an HTTP parser (or else it would have been GC'ed).

It would have been much easier to just find the point where we know
that the HTTP response object should be "finished", and forcibly
remove any references to it.


> Since you know "obj" can you set it to be a getter that returns undefined?

Yeah, but the purpose of this is to take *away* the ref that you
already *have*.  What good is a getter that returns undefined, once
you've already gotten it?  Closing the barn door after the horse has
left.


> Deleting all of the properties of obj would solve the problem as well I 
> assume.

But that is a bit more whack-a-mole, and expensive.  Ultimately, what
we did was move all of the addon properties on parsers to a single
object, and delete that object when we re-use the http parser.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


`free` operator

2012-10-25 Thread Isaac Schlueter
It'd be really nice if JS had a way to explicitly delete an object.

Occasionally, in complex programs, you can find yourself with a
situation where a certain type of object is leaking.  However, even if
you track down what the object is, and find the exact point in your
program where you ought to have no references to it, it's not always
obvious to know what might be holding a reference still.  It's
tempting to do this, and newcomers often think that this helps, but of
course, it does nothing:

function doStuff() {
  // some object that we're doing stuff with...
  someObject.someMethod()

  // now we know we're done, and there should be no refs.
  // but, there are, and they're leaking.
  // I know!  I'll do this:
  delete someObject
  // surprise! that does nothing.
}

What do you folks think about a "free" operator (or something like it)
that would actually do what `delete` looks like it does?

var obj = {}
var foo = { ref: obj }
var obj2 = obj
free obj  // obviously this syntax probably won't work, since 'free'
is not a reserved word already
assert(obj === undefined)
assert(foo.ref === undefined)
assert(obj2 === undefined)

So, any references to the freed object would be set to undefined, and
presumably at some point, the GC will harvest it.


Yes, yes, I know, the proper way to fix a memory leak in JS is to
properly manage references, but sometimes that means rewriting this
complicated app, and it's leaking memory now, in production.


Has this been discussed before?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-07-20 Thread Isaac Schlueter
Sorry for my long delay in responding.

On Fri, Jun 29, 2012 at 4:33 PM, David Herman  wrote:
>> var fs = require('fs')
>> // no path here...
>> function notCoveredByTests () {
>>  fs.open(path.resolve("yabbadabba"), ...)
>> }
>
> Right.
>
>> How would any of this solve that?
>
> Because `path` is unbound, and static variable checking reports that as an 
> error.

And this works because modules don't share global namespace with one
another?  (If they do share global space, then how would the static
checker know that it won't be assigned to a global 'path' by that
time?)


> I'm going to mull this more. I agree it's a worthwhile goal. But I'd like to 
> find a way to keep the syntax as lightweight as possible and yet not 
> interfere with static resolution.

Sounds good.  I'm interested in what you come up with.


> But we should not force this style on programmers.

It's not forcing anything on programmers.

If you want to export a bag of functions, then put the functions on an
object, and export the object.

It *is* making it trickier to figure out how to add types and macros,
but I'm less excited about those features than I am about making our
existing problems easier to solve.


> Even Node itself does not adhere strictly to that style -- look at the 'path' 
> or 'fs' libraries, for example.

I consider that a mistake.  And even there, there's a single "exports"
object that methods are assigned to.


> Same with the ES standard library: Math and JSON are both multi-export 
> (pseudo-)modules that just export functions.

They export a single object that has functions attached to it.
Math.pow(), JSON.parse, etc.

export { parse: parse, stringify:stringify }


> In these cases, there's no natural data abstraction needed, no class or 
> object with methods, just functions. To quote John Carmack, "Sometimes the 
> elegant implementation is just a function. Not a method. Not a class. Not a 
> framework. Just a function."

The Carmack quote is exactly why "export one thing" is so important.
Most modules should be a single function; not several things, not a
collection of utility methods.


>>> Moreover, it would be hostile to adding static constructs in the future, 
>>> such as macros, that can be exported from a module.
>> Can you elaborate on that?
> It took me a few days, but I wrote up some rationale for static module 
> resolution on my blog:
>
> http://calculist.org/blog/2012/06/29/static-module-resolution/

At the risk of seeming like a little bit of a luddite, it seems weird
to me to make the "modules that export stuff" use case (which we have
now) less awesome, in favor of the "modules that exports macros and
types" use case (which is not a compelling problem right now).

Granted, we don't have that use case because it doesn't exist.  But
maybe it could be done in a different way that doesn't necessitate
multiple exports.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-06-27 Thread Isaac Schlueter
On Wed, Jun 27, 2012 at 11:51 AM, David Herman  wrote:
> On Jun 27, 2012, at 11:15 AM, Isaac Schlueter wrote:
>
>> That was a bug caused by a lack of global isolation, which current
>> module systems cannot fix.
>
> It was caused by accidentally creating a global variable instead of a local 
> variable. Not totally sure what you mean by global isolation? If you mean 
> giving separate modules separate global objects, I don't agree that that 
> would solve this kind of bug. He doesn't show us the whole code, but it looks 
> like it was local code that was accessing the (accidentally) global variable, 
> but probably different event handlers were interleaving and causing data 
> races.

So, I've encountered two flavors of this in production, in my own
programs:  (The first in npm, the second in the no.de portal)

1. leaked global

app.route("/my/login", function (req, res) {
  x = res.query.x || 100
  if (x < 100) blerg()
})

In testing, you don't spot the leaked global, and things work, because
there's only one request at a time.  Linters all catch this, and tests
can check for leaked globals.

2. Module-local var

var x = someThing
// ... many lines later ..
app.route("/my/login", function (req, res) {
  x = res.query.x || 100
  if (x < 100) blerg()
})

A linter *won't* catch this, since it'll assume that you meant to do
exactly what you did.  Global isolation won't catch it either, and
neither will Harmony Modules or any existing require() thing.  (And in
fact, often you DO mean to do what this does!)

I think this is one of the cases where we just have to make
programming easier, by making choices that encourage smaller, more
discrete modules.


> Partly agree? I believe that obviating the *need* for globals is the core 
> purpose of a module system. I don't believe that modules should necessarily 
> be strictly separated. Modules should be given clean local scopes so that 
> they don't overwrite each other, but that doesn't mean they shouldn't be able 
> to still communicate via the global object.

Right, perhaps isolation is the wrong word.  Missing a "var" keyword
should not be so hazardous, that's what I'm saying.

> That bug was particularly bad because it was *assigning* to an accidentally 
> global variable. But in my personal experience I certainly forget to import 
> common libraries like 'path' and 'fs' in Node all the time and end up with 
> unbound variable references. When this happens in a control flow that got 
> missed by tests, then it can end up in production.

You mean something like this?

var fs = require('fs')
// no path here...
function notCoveredByTests () {
  fs.open(path.resolve("yabbadabba"), ...)
}

How would any of this solve that?


>> var Foo = require("foo")
>> var f = new Foo()
>
> Just import it directly:
>
> import Foo from "foo";
> var f = new Foo();

But wait... those are two different things, aren't they?  Isn't yours
more akin to: `var Foo = require('foo").Foo`?

> I just disagree. I think it's fine if you like that style [one module exports 
> one thing], and you can use it. But we shouldn't force it on users.

I'm having trouble articulating why it is that module.exports=blah is
better than exports.blah=blah.  Surely, you can just choose to only
put one thing on the exports object, right?  It seems obviously better
to allow the flexibility, and I was strongly in favor of this early in
node's history.

However, after using it a lot, I've found that `exports.foo = bar`
often ends up being more painful than `module.exports = foo`, even
with the transitive issues.  I'm not sure why that is, and "Go write
couple hundred KLoC of module JS and then you'll get it" is not an
argument, I know.


> Moreover, it would be hostile to adding static constructs in the future, such 
> as macros, that can be exported from a module.

Can you elaborate on that?


>> How does this proposal address transitive dependency cycles?
>
> Better than yours. ;-P
>
>> Unfinished export objects?
>
> The exports are all there from the beginning but uninitialized.

That's sort of like unfinished objects, then, but with the keys all
set to undefined.

So, then `export x = 10` hoists the `export x` and leaves the `x = 10`
where it is, var-like?

Does a_c === c, or not?


> Maybe! Happy to discuss. I don't believe there's that much boilerplate. In 
> fact, there's *less* boilerplate than either CommonJS or AMD, and compared to 
> your sketches on your post I suspect the differences in character count could 
> be counted on one hand.

It's quite a lot of new syntax, including special syntax for thi

Re: ES Modules: suggestions for improvement

2012-06-27 Thread Isaac Schlueter
On Wed, Jun 27, 2012 at 11:15 AM, Isaac Schlueter  wrote:
> import {myX: x, myY: y, z} from "foo"
> // comparable to:
> let {myX: x, myY: y, z} = require("foo")
>

Um.. I got the destructuring backwards, didn't I?


> Of course not. You can export a mutable object if you want to. You can export 
> whatever you want.

I seem to have missed that you already answered my question about
freezing.  Consider it withdrawn.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-06-27 Thread Isaac Schlueter
> Well, this was a relatively high-profile example:
>
>     http://blog.safeshepherd.com/23/how-one-missing-var-ruined-our-launch/

That was a bug caused by a lack of global isolation, which current
module systems cannot fix.  (Well, node *can* fix it with separate
contexts, but only by harshly penalizing performance and breaking
typeof, which we're not willing to do.)

I think we all agree that global isolation is the core purpose of a
module system.  (Is that incorrect?)

The question was whether there are in-the-wild bugs caused by typo-ing
export names in current module systems.


> The client chose to use *. You don't have to use * if you don't want to.
> It's a convenience.

It's unnecessary, afaict, and causes demonstrable harm in languages
that have it.  If it's just a convenience, then it should be cut out.


> Clients are disallowed from mutating another module's exports. (That's one
> of the things we're able to accomplish by making modules declarative rather
> than totally dynamic.)

Mutating *at all*?  Ie, they're frozen?  If I export an object, you
can't decorate it?  (If so, what does that restriction buy us?  It
seems kind of harsh.)


> Here I have no idea what you're talking about. Nothing about ES6 modules
> prevents you from locally controlling names. Local control over scope has
> always been one of the foremost principles of the entire design.

It's not exactly clear to me how I'd import foo's "x" as something
other than "x", from reading
http://wiki.ecmascript.org/doku.php?id=harmony:modules  (Admittedly,
I'm a lot better at parsing JavaScript than parsing JavaScript parsing
rules.)

Something like this?

import {myX: x, myY: y, z} from "foo"
// comparable to:
let {myX: x, myY: y, z} = require("foo")


Does this allow any way for the "foo" module to export *just* a single
thing, as the top level result?  How would this be expressed?

var Foo = require("foo")
var f = new Foo()

If the answer is "that's not supported", then I think that's a
significant gap.  It encourages a "one module = one thing" style and
is very easy to reason about.  It would be better to give up
multi-exporting in favor of exporting one thing, only.  If I could get
away with making that change in Node, I would have by now.


How does this proposal address transitive dependency cycles?
Unfinished export objects?

// a.js
import b from "b"
export a = b

// b.js
import c from "c"
export b = c

// c.js
import a from "a"
export c_a = a
export c = 10
// does c_a === c?

This was one area where I mentioned in my blog post that new syntax
for exporting seems like it might be warranted.  With require()
systems today, c_a is undefined, because the "c" export wasn't set
yet.  It's of course much worse when these are functions that call one
another.

All of the problems that I'm bringing up, which you're saying are
solved by the Harmony:Modules proposal, is it possible to solve them
with less new syntax and boilerplate?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-06-27 Thread Isaac Schlueter
On Wed, Jun 27, 2012 at 9:39 AM, Brendan Eich  wrote:
> First, what we propose is not type-checking.

Oh, ok.  I misunderstood.  Let's not say another word about type checking :)


> var foo = 42;
> ... foop ...
>
> throws at runtime in ES1-5 if evaluation reaches the foop use, and (if you
> wrap a module around that hunk of code, and there's no global foop property)
> at compile-time (EarlyError) in ES6.

I don't think that's a real problem.  Can you point to in-the-wild
bugs caused by this?  Maybe it's a failure of imagination on my part.

The "cost" I was referring to was:
1. added syntax
2. less obvious-for-humans-to-read programs

Consider:

module "foo" {
  export let x = 100;
  export let y = { z: 'zed' }
}

// far far away in another file entirely...
import * from "foo";
import * from "baz";
console.log(x) // what?  where did THAT come from?
x++; // do other importers of foo see x change? if so, spooky! if not,
why not? is it foo's x or not?
y.z = 'zoo' // surely that must be shared, right?

The compiler knows about x, but I don't.  This is probably my biggest
complaint about using C and C++.  Managing exported symbols is not
hard to automate, but it is hard to not-automate, and that makes it
more painful than just fixing the bugs.  Compare with:

var foo = import "foo";
console.log(foo.x) // maybe undefined, but so what?

We deal with undefined properties of objects all the time, and it's
not really such a big deal.  Typos are not a problem worth giving up
"export one thing" semantics for, and dealing with symbol conflicts is
worse.  Just let me call my vars whatever I want; when I ask for your
thing, give me your thing.  Dumping a bunch of symbols into my local
scope is intrusive.


> Second, you are "not at all convinced". Ok, that's either attitudinizing and
> padding an already long reply, or a line in the sand that doesn't say how
> you would be convinced, so unanswerable.

Sorry, you're right, that was unclear.

I would be convinced by examples showing bugs in modern programs that
would have been prevented by the proposed static export syntax.  Ie,
bugs that current state of the art module systems do not or cannot
address, and which are causing actual problems.


> We will never agree on "what JS is all about".

Well, apparently we do wrt static type checking, actually :)

But you're right.  I'll leave esthetics out of it.  Let's focus on practicality.


> You seem to say lack of typo checking is not a gap in the language. Is this
> a fair statement?

Yes that is a fair statement.  I don't see how we can add typo
checking without also adding "you get to tell me what to call my local
vars".  In every other place in the language, I get to decide what my
vars are called, and typo-checking happens locally, not at a distance.
 That's not a gap, that's a feature.

The main gap in the language that I'd like to see filled by a
module/loader spec is global leakage.  As I see it, the rest is simply
"how do we do that, without also removing module communication".
Removing global leakage removes global communication, so in
module-mode, we need a way for modules to communicate to one another,
and for the host system to know which programs to load.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-06-27 Thread Isaac Schlueter
I think a stand-up fight about this sounds wonderful.

I am not at all convinced that typo-checking is anywhere near worth
the price tag, or is even a problem.  Most of the alleged needs for
type-checking are a bit dubious to me; that's not really what JS is
all about.

It would be great for one of the static-export proponents to catalog
some current problems in the wild today that this would address, with
code examples that use modern module systems.


Re: Conditional Importing

Only allowing `import` at the top level sounds like an ok idea, but
I'm not so sure it's necessary.  Consider the current require() style:

if (some_rare_condition()) {
  foo = require('foo')
}

In requirejs and browserify the 'foo' module will be *defined*, but
never loaded (ie, prefetched, evaluated for deps, bundled, etc).  In
Node, it won't be read from the disk or evaluated (but if it's not
there ON the disk, you'll have problems eventually, which is
conceptually equivalent to having already been fetched, but without
the pre-run safety check.)

if (some_rare_condition()) {
  foo = import 'foo'
}

could be treated similarly.  There is an import statement, so resolve
it and define it.  However, it's never actually evaluated/run until
the first time the condition is hit, so the program text will be
parsed for `import`s, but never actually executed.

I am not aware of this being a surprise to many people in the current systems.


> It's true you can use today's JQuery as is, but why would you use a new 
> client API or syntax and require only new browsers or else trans-compilation? 
> What's the benefit?

I'm confused.  Isn't `module "jquery" { ... $teh.Codez() ... }`
already going to require only new browsers, as well as code editing or
trans-compilation?  Why is that less onerous than a new API or html
tag, especially when the tag can desugar to the API?

But, that being said, as I mentioned in the cited blog post,
auto-exporting the global is a bit weird, at least.  Making changes to
old libraries is costlier than we tend to think, but usually not
prohibitively so (and when it is, we just write new libraries).


I definitely agree that speculating about the future is hazardous,
which is exactly why I think that the module specification (and all ES
specs, actually) should focus on the problems we have today, and aim
to deliver value to today's programs.  We should look at current
common problems, and ask, "What is the minimum change to the
language's semantics and syntax that will make *this problem* go away,
without causing new problems, or preventing other solutions?"
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-06-26 Thread Isaac Schlueter
On Tue, Jun 26, 2012 at 4:48 PM, Wes Garland  wrote:
> On 26 June 2012 18:36, Aymeric Vitte  wrote:
>>
>> Node.js's way is good, except the "transitive dependency issue" mentioned
>>  in your post which in some cases indeed can cause problems.
> Does Node not handle transitive dependencies per CommonJS Modules/1.0?

Yes, node handles transitive dependencies via unfinished objects, much
like the old CommonJS Modules/1.0 style.

However, it's generally better to return a single thing from a module
if possible, rather than a bunch of stuff on an object.  We use
`module.exports` to accomplish that, and it's mostly good, but it
doesn't handle cycles well.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Modules: suggestions for improvement

2012-06-26 Thread Isaac Schlueter
The linked blog post is a very rough cut of where my thoughts are on
the subject.  Expect changes and cleanup.  It does not represent a
fully-baked (or even half-baked) idea, but more like a general
direction.

I expect to clean it up and propose something at least half-baked to
this list soon, incorporating some of the feedback that I've gotten
from that blog post.

On Tue, Jun 26, 2012 at 11:34 AM, Thaddee Tyl  wrote:
> Another point that I believe Isaac is making is that too much syntax
> is likely to confuse developers

Developers are very good at getting un-confused by new syntax, and
newbies are very good at becoming less new.  That's not *much* of a
hazard.

The bigger hazard is that we can't remove the syntax we add, and
historically, humans don't have a perfect track record at expecting
consequences, so we should try to reduce additions to the smallest set
possible to deliver the more important functionality.  In other words,
if some % of what we do is a mistake, we halve our mistakes by doing
half as much.  If we can focus what we do on the things that are very
essential to what we need, we can probably beat those odds :)

> and allowing certain features, such as
> nested modules or `import *`, can be harmful to programmer efficiency
> in the long term, if used.

Bingo.  Favoring the `exports` object instead of `module.exports` was
a mistake.  Implementing `import *` in Python and Java was a mistake.

Copying existing successful systems is good, but we should avoid
copying their mistakes if possible.


> Isaac, feel free to correct it.

Will do.  Probably not until after NodeConf early next week.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: optional "function" keyword

2012-03-08 Thread Isaac Schlueter
So, assuming that these two are valid function expressions that mean
roughly the same thing:

 a: (x) { return "x" }
 b: function (x) "x"

and then you might conclude that this is as well:

 c: (x) "x"

So far, so good, I think.

What about these?

d: (x) (y)
e: (x) (y) { return "z" }
f: (x) (y) ("z")
g: (x) (y) "z"

Leaving aside block lambda TCP freaky-deakiness, I'm not sure mentally
how to even parse those.  I suppose you could just say that you're not
allowed to start an expression-bodied-auto-return function with a (,
maybe?

I'm not sure.  But it is certainly weird and confusing.

If e and g both desugar to:

h: function (x) { return function (y) { return "z" }}

then that could be extremely useful to me.  Every ceremonial token has
been stripped, leaving only the meaningful bits.  It's especially
lovely for curry-able functions that are multiply-called:

i: curryableFn (a) (b) (c, d) {  .. do lots of stuff with a, b, c,
and d .. }

gogoAsync(args, curryableFn(1)(2)) // calls the resulting cb, a
and b pre-set.


On Thu, Mar 8, 2012 at 19:35, Kevin Smith  wrote:
> I think we can use a modification of the Dart technique to parse "=>"
> functions:
>
> On encountering "(" in a context where an expression is acceptable, you can
> try to parse it as ( Expression ) or as ( FormalParameterList ).
>
> Attempt to parse it as a formal parameter list, enqueuing each token
> encountered.  Either the parameter list will be successfully parsed or not.
>
>
> If a parameter list is successfully parsed, then
>
>   peek at the next token to see if it's a "=>".  If it is, then
>   clear the queued tokens and continue parsing as normal.
>   If it's not a "=>", then put the queued tokens back into the token
>   stream and restart parsing from the original "(", this time as
>   an expression.
>
> otherwise, if we fail to parse the parameter list, then
>
>   put the queued tokens back into the token stream and restart
>   parsing from the original "(", this time as an expression.
>
> Lemma:  The "lookahead" token stream that we queue while attempting to parse
> ( FormalParameterList ) will be identical to the token stream that we would
> have queued if we had attempted to parse ( Expression ).
>
> Thanks,
> kevin
>
>
> On Thu, Mar 8, 2012 at 4:28 PM, Kevin Smith  wrote:
>>
>> Thanks for the clear explanation, Brendan - I think I understand the
>> concerns now.  And if not, I don't mind looking foolish : )
>>
>> I just looked at the code for the Dart parser and it basically queues
>> tokens until it finds the matching right paren (recursively counting nested
>> parens).  It peeks at what comes afterward (like a => or {), and then it
>> goes back to the original left paren and resumes parsing, dequeueing the
>> already scanned tokens.
>>
>> Would this technique work for us?  The problem that I see is that in JS,
>> you can't really tokenize without also parsing (because of the cursed
>> lexical ambiguity on '/').
>>
>> kevin
>>
>>
>>
>> On Thu, Mar 8, 2012 at 2:35 PM, John Tamplin  wrote:
>>>
>>> On Thu, Mar 8, 2012 at 1:08 PM, Brendan Eich  wrote:

 Another which I cited just a few messages back: parsing ( params ) as (
 expr ), as any top down parser must until it gets to an arrow or other
 distinguishing token ({ on same line as ), e.g.), can be considered
 future-hostile. params should be declarative, but expr must now cover all
 future declarative syntax, including optional guards.
>>>
>>>
>>> For this particular problem, the Dart parser looks ahead to see if it
>>> could be a function declaration.  If so, it parses it that way, otherwise it
>>> parses as a parenthesized expression.  I don't know if this sort of approach
>>> would be considered acceptable here or not (it does impose some restrictions
>>> on the scanner for n-token lookahead).
>>>
>>> --
>>> John A. Tamplin
>>> Software Engineer (GWT), Google
>>
>>
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: optional "function" keyword

2012-03-07 Thread Isaac Schlueter
This might be a dumb question: TCP = "this-context preservation"?
(Sorry, my brain has that acronym hard-linked to "Transport Control
Protocol" and I keep getting confused.)

On Wed, Mar 7, 2012 at 13:01, Gavin Barraclough  wrote:
> But (modulo separate "do" TCP proposal of yesterday) shorter function syntax
> is just syntax. No TCP, no lexical |this| in particular.

Yes, "functionless function" proposal is just syntax, not a change in
semantics.  IIUC, reducing the syntax weight of callable-things
(whether functions or freaky-deaky lambda things) is a goal in itself.

Assuming that we get "() do {}" as the freaky-deeky syntax, would that
do the TCP stuff?  If so, why not drop block-lambdas, and do the TCP
stuff by saying that single-return-expression functions are the ones
that do TCP and other freaky stuff?  Then you can treat "do {...}" as
an expression, somewhat like a block lambda that takes no arguments
and is invoked when evaluated.

Then you really have three somewhat modest proposals:

1. optional "function".
2. braceless functions that auto-return the completion value of the
expression and exhibit TCP freakdeekness.
3. do-expressions blocks that evaluate to their completion value.

These three seem to combine to let you do all the good things that
block lambdas offer, and are pretty elegant and easy enough to explain
to new users, IMHO.  The "do" token sort of looks like it means "Do
this right here, not in a separate context".

It seems like #2 would require the most ironing out.  For example: `x
= (y) +1` is ambiguous, as is `x = (y)(z)` and many many others.  If
we use `do {...}` (or something) as an unambiguous "this is an
expression", then that could be a nice escape hatch.  Ie, `x = (y) do
{ 1 }` would be akin to `x = tcp_freaky_deeky(function (y) { return 1
})`.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: optional "function" keyword

2012-03-06 Thread Isaac Schlueter
I'd suggest dropping the

   Identifier_opt ( FormalParameterList_opt ) [no LineTerminator here]
IniitialValue

production.  Wouldn't that mean that you could have something like this?

var allA = list.map(() "a")

I think the curly braces are ok here.  Hated keywords should be
attacked one at a time, imo.


On Tue, Mar 6, 2012 at 12:42, Brendan Eich  wrote:
> Brendan Eich wrote:
>>
>> ShortFunctionExpression:
>>    Identifier_opt ( FormalParameterList_opt ) { FunctionBody }
>>    Identifier_opt ( FormalParameterList_opt ) IniitialValue
>
>
> Let's try that again:
>
> ShortFunctionExpression:
>    Identifier_opt ( FormalParameterList_opt ) [no LineTerminator here] {
> FunctionBody }
>    Identifier_opt ( FormalParameterList_opt ) [no LineTerminator here]
> IniitialValue
>
> But of course the second production creates bad ambiguities for all
> InitialValue bodies that start with an operator or punctuator that could be
> infix as well as prefix: +/-/[ at least.
>
> More work needed. I may write a strawman up. Encourage me!
>
> /be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: optional "function" keyword

2012-03-06 Thread Isaac Schlueter
On Tue, Mar 6, 2012 at 12:06, Brendan Eich  wrote:
>> Yes, an identifier is required.  It would not be possible to define an
>> unnamed function in this way.
>
> Why not express an anonymous function, though? Definition != expression. As
> usual, an expression *statement* could not start with ( and consist entirely
> of a function-keyword-free anonymous function expression.

I see.  So, you'd be suggesting using:

( args ) { functionBody }

as an anonymous function expression, though not a function expression
statement? What about these?

;(( args ) { functionBody })
!( args ) { functionBody }

Certainly, this is quite nice:

myList.forEach((item) { .. })


> Dart has mandatory semicolons to help avoid trouble around the edges of
> statements/definitions.
>
> Candor is new, so no one has deep experience.
>
> To get further we'd need some brave souls to try this out with a trivial
> transpiler, at scale.

True that.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: optional "function" keyword

2012-03-06 Thread Isaac Schlueter
On Tue, Mar 6, 2012 at 10:53, Brendan Eich  wrote:

> This approach requires a restriction: [no LineTerminator here] between the
> ) and the {:
>

Yes, I did put that in the OP, but it looks like my mail client helpfully
wrapped at that point, which is a bit confusing :)

Leaving out the f in the "definition" doesn't help, since (a,b,c) is a
> comma expression. The requirement is no LineTerminator between the ) and
> the {.
>

Yes, an identifier is required.  It would not be possible to define an
unnamed function in this way.



> Without a leading keyword, it's harder to find the functions. Not
> impossible, not saying this is a deal breaker. But it is harder.
>

Agreed. This was inspired by seeing some code in candor and dart, and
getting jealous of their nice terse functions :)  However, having not used
this style in real programs, it's hard to comment on whether it would
continue to be nice, or get annoying.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: optional "function" keyword

2012-03-06 Thread Isaac Schlueter
On Tue, Mar 6, 2012 at 10:07, Thaddee Tyl  wrote:

> An interesting property of this syntax is that anonymous functions can
>
be written this way:
>
>myList.forEach(λ (item) { doWith(item) })
>
> (it can also be `lambda (item) { ... }`)
>

Yes, any valid function identifier could be used, because it's not actually
a keyword.

_ (arg) { ... }
f (arg) { ... }
$ (arg) { ... }
ƒ (arg) { ... }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


optional "function" keyword

2012-03-06 Thread Isaac Schlueter
A great many letters have been typed regarding the number of letters in the
word "function".

What if we just made the keyword "function" entirely optional, dart-style?

*ShortNamedFunctionDeclaration* *:**Identifier *** *(* *
FormalParameterListopt* *)  {* *FunctionBody* *}**
ShortNamedFunctionExpression* *:**Identifier *** *(* *
FormalParameterListopt* *)  {* *FunctionBody* *}*Note that
the identifier is no longer optional, and that no linebreak is allowed
between the parameter list and the body, unlike current function decl/exprs.
myList.forEach(x (item) {
  item += 2
  doSomethingElse(item)
  assert(typeof x === "function")
})
// expression, not declaration
assert(typeof x === "undefined")

// declaration, hoisted
assert(typeof doSomethingElse === "function")

doSomethingElse (item) {
  // IIFE, not declaration
  ;(y (n) { item += n })(Math.random())
  assert(typeof y === "undefined")
}

Is there an obvious case I'm overlooking where this sort of construction
would fail?  Clearly, you can't put the { on the next line or else it'll be
interpreted as an invocation followed by a block, and that could be a
significant footgun.  But, it's not a *new* footgun, since \n{ is
problematic with return anyhow. (I long for a mode where \n{ is always a
syntax error.)  And, it introduces no new keywords, no syntax that isn't
already an error, and no new semantics.

I'm eager to see what I missed when you shoot this down :)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Jan 18 meeting notes

2012-01-20 Thread Isaac Schlueter
On Wed, Jan 18, 2012 at 17:27, Waldemar Horwat  wrote:
> Octal constants:
> Useful as arguments to chmod.
> Proposal for 0o123 (as well as 0b01110).
> MarkM: Concerned about 0O123.
> Waldemar: Nothing unusul here. We've lived with 36l (meaning 36 long instead
> of 361) in Java and C++ for a long time.
> Alternative for octal: 8r123 (but then we'd also want 16r123, 2r0101, and
> maybe more).
> Decided to allow 0o and 0b.  Unresolved whether to allow 0O and 0B.
> Persistent weak feelings on both sides on the upper case forms.

On behalf of Node.js, thank you.  This is the right call.

FWIW (ie, not much), I'm personally 100% ambivalent about 0O and 0B.
0O is less visually distinctive than 0o, and caps support isn't really
necessary.

Nr### is not really necessary. Programming happens primarily in bases
2, 8, 10, and 16.  (And 64, but that's mostly just for serializing.)
If we have 0b, 0o, 0x, and the default base 10, then that's plenty.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Better Native XML Support

2012-01-17 Thread Isaac Schlueter
I think that requiring a user load a parser to handle XML is perfectly
fine.  That's the state of the art in most programming languages.

On Mon, Jan 16, 2012 at 09:51, David Bruant  wrote:
> Le 16/01/2012 18:30, Nuno Job a écrit :
>> Hi guys,
>>
>> I would like to make the case for better native XML support in ES5:
>>
>> This is the most commented open issue on V8:
>> http://code.google.com/p/v8/issues/detail?id=235
>> Unfortunately people didn't agree on E4X and this makes the life of
>> developers that have to use XML miserable. While XML is not a first
>> class citizen in the web it is the preferred interchanged format in
>> the enterprise. Developers don't choose to use XML over JSON, they
>> sometimes have to use XML. A solution for this would be always better
>> if in the language.
> Have a look at quasis [1]. It provides what I'd consider to be a more
> generic and safer solution to E4X.
> You can send feedback to es-discuss@mozilla.org (es5-discuss is usually
> reserved to ECMAScript 5 specifically, though most people who are in one
> are certainly in both)
>
> David
>
> [1] http://wiki.ecmascript.org/doku.php?id=harmony:quasis
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Thoughts on WeakMaps

2011-06-07 Thread Isaac Schlueter
On Tue, Jun 7, 2011 at 13:59, Mark S. Miller  wrote:
> There's no where in the standard API of the ES5 built-ins that does this
> return-self pattern for purposes of chaining. There are of course JS
> libraries, like jQuery, that make pervasive use of chaining. However,
> ES-next built-ins should first respect the precedent of the general style of
> other built-ins, in order to be least surprising.

+1

IMO, the "return the set value" approach seems to make the most sense,
since map.set(k, v) is conceptually akin to obj[k] = v.  I've always
liked that about the HTMLElement.appendChild() function.

They're all easy enough to monkey-patch, so this seems a little
bikesheddy to me.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Is class syntax really necessary ?

2011-05-23 Thread Isaac Schlueter
On Mon, May 23, 2011 at 08:51, Brendan Eich  wrote:
> Class syntax is like a lint brush for such features. If we add it, it will 
> accrete more semantics (with unambiguous syntax, I hope) over time. This is 
> just inevitable, in my view. It makes me want to resist classes and look at 
> smaller and more direct fixes for the two known prototypal hazards.

Yes, please!

I assume "two known hazards" is referring to your previous email:
"subclassed prototype/constructor set-up and super calls."

I've been using this pattern in my OOP javascript programs lately:
https://github.com/isaacs/inherits/blob/master/inherits.js

It works really well, behaves as expected (easy for the author to say,
ha, but it doesn't violate instanceof, doesn't call ctors more than
once, doesn't clobber already-added prototype properties, etc.)  And
it's about 10 lines, easy to read and grok.

What would make it even nicer, however, with minimal added syntax:

1. Call "super(a, b, c)" instead of "Child.super.call(this, a, b, c)"
2. Maybe Parent.extend(Child) or Child.inherit(Parent) instead of
inherits(Child, Parent)
3. Right now, calling parent versions of overridden methods is a
painful: "this.constructor.super.prototype.someMethod.call(this)".
It'd be nice to use something like "super.someMethod()".
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Short Functions

2011-05-22 Thread Isaac Schlueter
On Sun, May 22, 2011 at 16:05, Brendan Eich  wrote:
>> Cutting out many kilobytes of code from JavaScript programs by
>> streamlining the single-most commonly-used idiom is hardly frivolous.
>
> The counterargument, I don't share it but you seem to be focused on 
> bandwidth, is transfer-encoding compression, gzip.

I think you and I agree on this point.  Syntax should be judged based
on the costs to fingers and brains.  In this regard, I think that
writing and reading a lot of bytes for a frequent idiom is a bad
thing.  It's about bandwidth across neurons, not wires.

Towards that end, I see a lot of promise in the arrow-function proposal.


>> In fact, I'd argue that it should be one of the main goals of this
>> list and of TC-39.
>
> We should have short syntax as a main goal? That hits return too.

Indeed it does!  That being said, implicit returns are a bit thornier
problem for their security implications.


> It arguably means block lambdas, since they are more concise
> and more expressive. But you demur from them below, so brevity
> can't be the top "main goal".

I don't think that brevity should be the primary goal of Harmony or
es-next, no.  But I do think it should be an important consideration.

Brevity is not a value in itself.  It is a value when the shorter
syntax reduces the overall cognitive burden.  Code that is easier for
humans to think about, tends to also be easier for humans to not mess
up.


>> The complications have not been very well explored, and are not
>> trivial, in my opinion.
>
> They have been explored in other dynamic languages. They're not that bad.

Yes, I guess we are pushing opinions at each other.  I'd say that they
are that bad.

I have experience only with Ruby, not SmallTalk or E.  Maybe they're
handled better in the other two?


>> I am also unconvinced by the "looks like a block" argument.  The body
>> of a es-current function also "looks like a block",
>
> No. That's not the relevant comparison. The issue is whether the whole
> function-or-block-lambda-expression "looks like a block".

That was the point I was trying to make.  Having block-lambdas behave
like functions is not a hazard.  "||" is enough of a differentiator,
just like "function ()" is, only with a little less to look at.


On Sun, May 22, 2011 at 16:36, Brendan Eich  wrote:
> To reverse the argument you made: if function body looking like a block
> were a source of confusion, we'd already have trouble:

I'm not saying it's a source of confusion.  I'm saying "this callable
thing is dramatically different than that other callable thing" is a
bigger hazard than "this curly-brace is dramatically different from
that other curly-brace".


> But people do not read the return above as returning from function outer. Why 
> not?

Perhaps because callables in JavaScript are all the same, and only
ever return out of themselves, never their parent scope.  (Of course,
ctors called with "new" aren't quite identical to normal functions,
because of the implicit "return this".  But that is a determined by
the call style, not by the function type, and is a much smaller
difference.)


> More likely, the distinctive function () head syntax before the
> body block made it clear.

As |arg| would as well.

My point there was that "looks like a block" is something of a stretch
as an argument for or against anything.  Object-literals look like
blocks with labelled lines, but we don't seem to have any problems
with those (except when we do, of course; qv. every JS repl.)


Here's the sort of thing that I'm driving at:

function abc (cb) {
  if (Math.random() < 0.5) cb(100)
}
function xyz () {
  abc( {|x| return x } )
  return 10
}
var p = xyz()

The fact that a conditional in abc() can trigger a return in xyz,
without transferring control back to the calling function first, seems
surprising to me.

The situation is further complicated when dealing with asynchronous
code.  If I'm not mistaken, the following will throw if readyToGo()
returns false, yes?

function abc (cb) {
  if (readyToGo()) cb()
  else setTimeout(cb, 100)
}
function xyz () {
  abc( {|x| return x } )
  return 10
}
var p = xyz()

Changes to flow control semantics have subtle implications.  Perhaps
user-testing will bear out that my taste is in the minority, and that
the abuses are lesser or no worse than what we already deal with, I
don't know.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Short Functions

2011-05-22 Thread Isaac Schlueter
On Sat, May 21, 2011 at 23:07, Sami Samhuri  wrote:
> The semantics have shortcomings though and introducing new syntax to save a
> few keystrokes is frivolous.

Cutting out many kilobytes of code from JavaScript programs by
streamlining the single-most commonly-used idiom is hardly frivolous.
In fact, I'd argue that it should be one of the main goals of this
list and of TC-39.

Adding new semantics to the language seems frivolous to me, if doing
so does not solve problems we actually have today.  Lambda-blocks, as
proposed currently, adds considerable surface area to the language
without providing any real value.

The complications have not been very well explored, and are not
trivial, in my opinion.

I am also unconvinced by the "looks like a block" argument.  The body
of a es-current function also "looks like a block", and no one seems
to have a problem with it.  Shall we say that "return" in a while loop
should be a break, because its body "looks like a function body"?

```
// 1: a current function
x = someArray.map(function (x) {
return x * x
})

// 2: a lambda-block
x = someArray.map({ |x|
return x * x
})

// 3: a current block
for (i in x) {
return x[i] * x[i]
}
```

Who's to say that the lambda-block[2] "looks like a block[3]" any more
than the regular function[1]?  It's extra syntax above and beyond a
current block in either case, and in fact, because it can be wrapped
in parens (since it's an expression), it behaves in the language
*much* more like a function than like a block.

The fact that {||}-style blocks can be passed and assigned to
variables makes it remarkably more complicated to reason about them if
their return/break/continue semantics are different from existing
functions.  Because of the fact that they are expressions which can be
manipulated, they are more akin to functions than to blocks.

The examples from Claus and Allen fill me with trepidation.  Please
don't do this awful thing.  It is the problem with Ruby.  We don't
need to invent new versions of "for" and "while" in every program.
JavaScript's minimal semantic surface is a strength, not a
shortcoming.

At the very least, the implications of this semantic change need much
much more exploration than the other short-function proposals.  I
realize that it's exciting, but the best footguns typically are.

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Short Functions

2011-05-21 Thread Isaac Schlueter
I very much want short functions.  However, the semantics of
JavaScript lambdas are so wonderfully simple.

Adding a semantically different callable thing is a huge mistake, in
my opinion.  I'd love to be able to write

{|a, b, c|  a + b * c }

or even

(a, b, c) -> { a + b * c }

or

#(a, b, c) { a + b * c }

instead of

function (a, b, c) { return a + b * c }

but I really don't want to replace our existing simple semantics.

I see a lot of the discussions of short function syntax seeming to
imply ruby-block semantics, with the "return returns from the parent"
idea.  It would be great to separate those two concerns.  They are
very different.  One is sugar, the other is a much more radical change
to the way the language works, which I'm not altogether convinced is a
good or useful thing.

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Function Syntax

2011-05-10 Thread Isaac Schlueter
As always, very well put, Douglas.

On Tue, May 10, 2011 at 16:53, Douglas Crockford  wrote:
> ECMAScript has a large set of problems. I think that the fact that 'function'
> has eight letters is at the bottom of the priority list. And yet, I am open to
> the possibility of introducing new syntactic sugar to the language to make
> the expression of functions more elegant.
>
> I look at ECMAScript as serving four groups:
>
> 1. The beginners for whom the language was designed.
> 2. The web developers who owe their livelihoods to the language.
> 3. The scientists who will use the language for greatness.
> 4. Language designers and critics.

I think that there is a very subtle way in which Ruby's blocks are
perceived, largely because they involve less ceremony than
JavaScript's functions.  Making the expression of functions more
elegant will go a long way towards making newcomers grok their
importance and power, as well as a lot of typing (and visual clutter)
for those of us in the second group.

> Some of the proposals and wishes for new syntax are alarming, in that they
> appear to be increasing the problem set, rather than reducing it. For
> example,
> the language has a confusion between blocks and object literals. Any new
> syntax
> should reduce or eliminate this confusion, not amplify it.

+1.

> I want to make the language easier to beginners to learn, streamlining the
> syntax, replacing automatic semicolon insertion with statements that are
> by design semicolon free.

Some of us are already writing JavaScript this way :)

The newline elision thing is unnecessarily persnickety, though.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: arrow syntax unnecessary and the idea that "function" is too long

2011-05-10 Thread Isaac Schlueter
On Tue, May 10, 2011 at 16:22, Oliver Hunt  wrote:
> \ is a much more common lambda symbol in many languages, and i'm not sure 
> what the ambiguity would be in \{...} or \(...){...}.

\(a,b,c) { a + b * c }

That's cute.


> I'm also really not happy with the concept of minor variances in syntax 
> having such dramatic impact the language semantics.  All the fiddling with 
> |this| dramatically increases the complexity of the language, it doesn't 
> simplify it.

I completely agree.  It think any short-form function syntax should
have the exact same semantics as the existing long-form.  We've got
.bind(obj).  That's enough.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: arrow syntax unnecessary and the idea that "function" is too long

2011-05-07 Thread Isaac Schlueter
I wrote PHP full time for years.  -> can get pretty aggravating.  # is
50% shorter, and doesn't use the same fingers that type the ().  ()->
is a lot of right-hand-dancing.

That being said, it does look pretty nice, and we're all just going to
set our editors to do that for us anyhow, right?

On Sat, May 7, 2011 at 20:52, Faisal Vali  wrote:
>> "Kyle Simpson" 
>> Date: Sat, 7 May 2011 21:58:32 -0500
>> Subject: Re: arrow syntax unnecessary and the idea that "function" is too 
>> long
>
> 
>
>> With all due respect, Brendan's personal tastes on what kind of code he 
>> likes to write is not enough.
>> It has to be something that is likely to find wide spread support among the 
>> JavaScript masses.
>>
>
> Since the arrow syntax assailants have been quite vocal on this list,
> lest they be construed as representative of the javascript masses, I
> would like to voice a strong endorsement for pursuing and exploring
> the arrow syntax further - and I do this as a simple javascript
> hobbyist who uses javascript (and JQuery, for lack of the perfect
> library) extensively to automate tasks on windows (via htas) and to
> write RIAs.
>
> With all due respect to Mr. Simpson's personal tastes, I find the
> aesthetics of the arrow-syntax far more consistent with javascript's
> C-based-syntactic roots than the preprocessor-tainted '#' - but I
> also recognize that my personal aesthetic tastes are just that.
> Anyway, I hope that enough general users share my aesthetic and
> usability preference (short syntax for functionally well behaved and
> intuitive lambdas with closure capability) that the arrow syntax is
> given some serious thought and not dismissed because of this thread.
>
> Thanks!
>
> Faisal Vali
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: arrow syntax unnecessary and the idea that "function" is too long

2011-05-07 Thread Isaac Schlueter
It has been my experience that professional JavaScripters will cheer
*any* idea that shortens the spelling of "function" and "return" :)

Brendan has said that 8 characters for "function" is at least 6 too
many.  I think it's probably at least 7 too many.  But it'd be a shame
to remove the character-count-tax only to introduce a
twisting-wrist-tax.  I'd prefer something closer to the middle of
(most) keyboards than -> or {|.  #() is pretty nice, actually.

When I suggested "doing away with blocks", I of course was not
referring to structures where the block is relevant, such a function
bodies, if/else, try/catch/finally, or loops.  I was talking about
having a bare unadorned block in JavaScript.  These are relevant in C,
where you have block-scope, but in JavaScript have only made it
trickier to know whether something is supposed to be an Object-literal
or a block with labelled lines.  For example:

return {
  foo: "bar"
}
// vs
return
{
  foo: "bar"
}



On Sat, May 7, 2011 at 14:39, Claus Reinke  wrote:
>   function bodies extend as far as possible **

I see.  So, a function body would be just like an if-block or loop
body.  One full statement, or a block.  There is precedent for that in
the rest of the language.  So, then, this case:

x = function () y; z

would be:

x = function () { return y }; z

am I understanding that correctly?

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: arrow syntax unnecessary and the idea that "function" is too long

2011-05-07 Thread Isaac Schlueter
For what it's worth, I'm a *huge* fan of Ruby's {|-style blocks.
Also, it's worth noting that "do...done" seems to be a bit more
popular in Ruby programs that I've seen.

I'm not a fan of the fact that these blocks have different behavior
than "regular" functions and methods, but that's a qualm for a
different mailing list, and I'm not a rubyist anyhow :)

Consider this: w = (x)->y || z

That code is not obvious at all.  Which of these would it be?

1: w = function (x) { return y } || z
2: w = function (x) { return y || z }

It seems to me that there must be some sort of delineation around the
function start and end.  I agree that "function ... return" is way too
many characters to write and read for such a fundamental bit of
syntax.

This style is quite clear and readable:

w = {|x| y || z}
w = {|x| y} || z

However, that's pretty awful to type.  Perhaps even worse than ->.
Maybe {(x) y || z} might be better?  Of course, that would break
blocks that start with parenthesized sequence blocks, but is that
really a concern?  Blocks in JS are useless, can't we just do away
with them?

On Sat, May 7, 2011 at 10:04, Peter Michaux  wrote:
> On Sat, May 7, 2011 at 9:56 AM, Thaddee Tyl  wrote:
>
>> JavaScript is still seen as a badly object-oriented programming
>> language by those who still think it is java with a weird syntax.
>
> I think that concpetion has declined a lot as rich clients have forced
> people to become better acquainted with JavaScript and a lot more has
> been written on the language.
>
>> I do
>> hope it grows to be known as an outstanding functional programming
>> language.
>
> JavaScript won't ever be known as a outstanding functional programming
> language until it has proper tail calls. This would give the language
> new capabilities it doesn't have now.
>
> Peter
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic Semicolon Insertion: value vs cost; predictability andcontrol; alternatives

2011-04-19 Thread Isaac Schlueter
On Tue, Apr 19, 2011 at 11:53, Jorge  wrote:
>> Which minifiers?
> I don't know, the ones that make "web apps burn in hell if they are missing 
> semicolons".

Until someone can point to an actual minifier that's actually affected
by this, I think the whole "minification requires semicolons" argument
is baseless fud.

Not trying to impugn you specifically.  It takes a lot of work to
un-believe something that "everybody knows" :)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic Semicolon Insertion: value vs cost; predictabilityandcontrol; alternatives

2011-04-19 Thread Isaac Schlueter
On Tue, Apr 19, 2011 at 11:02, Garrett Smith  wrote:
> On 4/19/11, Brendan Eich  wrote:
> I don't mean to annoy by repeating the same things, but here goes: Is
> `()` Grouping Operator or Arguments? Is `[]` ArrayLiteral or Property
> Accessor? Or do these cases depend on the preceding token?

They depend on the preceding token, *and* they cause a preceding \n to
be elided.  That is the problem with JavaScript's statement
termination rules with respect to lines that start with +, /, *, -, (,
or [.

> Now concatenate a.js and b.js and you have:
> var MyWidget = function(){
>  this.name = "mike";
> }(function() {});

That error isn't caused by ASI.  Disabling ASI won't prevent that error.

That error is caused by the lack of ASI.  It's caused by the \n being
elided when the next line starts with a (.

>> So any statement of the form "... ASI changes program behavior WRT
>> unrestricted productions is bigger problem" is simply misstated.
>>
> See above.

ASI didn't change the program behavior.  ASI didn't happen in that example.

Newline elision changed the program behavior.

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic Semicolon Insertion: value vs cost; predictability andcontrol; alternatives

2011-04-19 Thread Isaac Schlueter
On Tue, Apr 19, 2011 at 09:57, Jorge  wrote:
>> Most web apps will burn in hell if they are missing semicolons when you 
>> minify them.
>
> Indeed, for some minifiers it's a must.

Which minifiers?

Closure, yuicompressor, jsmin, packer, and uglify all handle ASI
without so much as a complaint.  In fact, with YUICompressor and
JSMin, at least, when you omit semicolons, you end up with more easily
debuggable minified code, since the line numbers in stack traces are
actually helpful.  (No "line 1, char 82,343" to deal with.)

> These minifiers avoid (understandably) the hassle/expensiveness of building a 
> parse tree and rely on (clever!) tricks that in turn require the programmer 
> to put every semicolon in the source text, as if post-ASI, explicitly.

I don't believe that "those minifiers" actually get much use.  They're
hideously broken, and there is a huge selection of competent minifiers
that do actually minify JavaScript properly.

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic Semicolon Insertion: value vs cost; predictabilityandcontrol; alternatives

2011-04-19 Thread Isaac Schlueter
On Mon, Apr 18, 2011 at 22:52, Garrett Smith  wrote:
> On 4/18/11, Claus Reinke  wrote:
>>> The only places where semicolons are ever used in the Node.js package
>>> manager are in the 'for' loops headers and at the *beginning* of the lines
>>> that would be interpreted incorrectly because of the lack of the semicolon
>>> at the end of the *previous* line - for example see:
>>> https://github.com/isaacs/npm/blob/master/lib/utils/read-json.js#L320-L336
>>>
>>> There are no semicolons at the end of lines *at all*.

npm author here.

> If you can think it, there is a porn for it.

It's not syntax porn, I assure you.  This style is more easily
scanned.  The important tokens are along the left edge, which forms a
straight line with logical and orderly breaks, and those tokens are
not overused, so their presence or absence is very noticeable.  The
right-edge is jagged, and when every line has a ";", the brain tends
to filter out their presence, making it hard to notice their absence.

Maybe your brain doesn't have the same pattern-matching style as mine,
of course.  But, willy nilly, I have the brain I do, so I made npm
look the way it does, so that it's easier for me to avoid and find
bugs with a minimum of friction.

This is all to say, relying on ASI is (sometimes) a sane and pragmatic
decision, and not difference for difference's sake.


> Restricted productions are the most benign cases. How ASI changes
> program behavior WRT unrestricted productions is bigger problem.

Can you provide examples of the sort of unrestricted productions
you're referring to, where unexpected "semicolon insertion" changes
program behavior?  In my experience, it is the *lack* of ASI that
usually causes problems with unrestricted productions.


>> In brief, there is no way simply to take away ASI, and any
>> attempt to introduce a less troublesome variant of ASI will
>> have to offer a way to deal with existing code.
>>
> The number of developers advocating ASI as a "best practice" can't be
> stopped either.

Developers using ASI and advocating its use should be taken as a
datapoint for our discussion of the language, don't you think?
Regardless of whether or not you agree with them, breaking their model
drastically will only result in a lower adoption of
Harmony/es-next/opt-in-whatever.


>> As a coder, you really don't want to add semicolons to
>> avoid ASI traps, as in line 232 of your example
>>
>>     ;["dependencies", "devDependencies"].forEach(function (d) {

Yes.  I've never started a line with [ with the intent of it being a
property access.  I do sometimes start a new line with ( for a
function call, if the list of arguments is long, but it's a practice
I'd gladly change in exchange for saner statement ending rules.


> Why do I want to have to worry about what might have been omitted? No,
> I want to worry about what the code says. I consider a statement
> terminator to be just that; when I read it, I see end of statement.
> don't want to read beginning of statement preceeded by empty
> statement.

In that case, what the code "says" is exactly the same, whether the
semicolon is on the next line or not.

There is nothing fundamental or essential about ; being a "terminator"
rather than a "separator".  In fact, that's what it actually is in
EcmaScript - a statement separator.  (Likewise in sh/bash/zsh, Perl,
Ruby, Erlang, and many others.)  In Java, PHP, C, and C++, it is a
terminator.  This isn't c-devel or java-devel, it's es-devel.

The "use superasi" pragma would effectively make [ and ( treated a bit
like restricted productions, in that a line break before them *always*
terminates the statement.  I'm not sold on this idea, necessarily, but
I think it's important to consider options other than how to remove
ASI from the language.

> Exactly. Multiline comments add extra problems.

How so?

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic Semicolon Insertion: value vs cost; predictability andcontrol; alternatives

2011-04-18 Thread Isaac Schlueter
On Mon, Apr 18, 2011 at 12:22, Brendan Eich  wrote:
> I agree, but in a friendly spirit suggest typing ; is a tax too, however much 
> lesser.

True, I overstated.  It *is* a keyboard tax.  But (at least in my
experience) I tend to type code in a moment, and then read it for the
rest of my life.  I'd gladly pay a keyboard tax that lowered the
cognitive burden of maintaining code.

> Some expressions that do not involve calling, assigning, or otherwise 
> potentially having effects (declaring, where the declaration is a misplaced 
> function expression) still may have effects (e.g. getters).

> Your suggestion seems to be to avoid analysis and warn based only the syntax 
> of the expression that follows on a separate line a bare, unterminated 
> return. I think I agree, but I wanted to call this choice out for more 
> discussion.

> Indentation, yay. Necessary in your view, or could you just ignore everything 
> except the separation by a line terminator?

Thinking about this a bit more, I think maybe this whole suggestion is
a bad idea.  Forget I said anything.  Significant linebreaks are one
thing, but significant indentation is deeply problematic.

Maybe the solution is a way to make return's expression non-optional?
If you want to return nothing, then you'd `return undefined` or
`return null`.

In any event, I think spending a lot of effort trying to figure out
the best way to remove ASI from the language is an unprofitable path.
That energy would be better spent trying to figure out how best to
remove just the problems with the current ASI implementation, and not
throw out the baby with the bathwater.

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic Semicolon Insertion: value vs cost; predictability andcontrol; alternatives

2011-04-18 Thread Isaac Schlueter
On Mon, Apr 18, 2011 at 11:05, Brendan Eich  wrote:
> Given the primary problem is not ASI but its absence where users expect it 
> due to mistakenly believing a newline is significant, one could argue the fix 
> is not to ban ASI and tax everyone with writing lots of insignificant 
> semicolons (in some opt-in mode hardly anyone would use, which would only 
> crud up implementations' parser state spaces).
>
> One could argue instead that we need *more* newline signfiicance.

Yes.  This is the sanest thing I've read in this thread.

How about this?

"use superasi"

Result:

1. /\n\s*[\[\(+*\/-]/ is a syntax error.  (Or should it silently do
ASI here?  Not sure.)
2. /;\s+\n/ is a syntax error. (No extraneous semicolons.)

This would enforce proper use of ASI, and turn off the problems where
statements are confusingly not ended by \n.

(Starting a line with a "." should still be allowed, since that is not
otherwise a valid construction, and thus not easily confused.)

Arguments for:
1. Mostly backwards compatible, except in the case which everyone
seems to agree is a language defect.
2. Prevents the wtfs that are cited as being due to ASI.
3. Encourages developers to know the language they're using.

Arguments against:
1. Ew.  There aren't semicolons there.

--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Fwd: Automatic Semicolon Insertion: value vs cost; predictability andcontrol; alternatives

2011-04-18 Thread Isaac Schlueter
On Mon, Apr 18, 2011 at 05:42, Jorge  wrote:
> I understand that it would be quite interesting to get a warning/error in
> this case:
> a= b
> (c= d)();
> ...only that there's no ASI in this case !

Jorge touches on the reason why the whole debate about ASI is a bit
misguided, in my opinion.

The "} or \n ended a statement" ASI doesn't usually bite, except in
the case of restricted productions, where it looks like it wouldn't
end.

   return
     { a : 1 };

This is a situation that's extremely easy to avoid with a simple and
easily lint-able rule: "return\n is an error".

However, is it reasonable to treat strike this ASI with the same hammer?

   b.on("click", function () { alert("hi!") });

I don't think so.  No reasonable JavaScripter would be surprised that
the alert line ended at the }.

Furthermore, it is not the existence of ASI, but rather the lack of it
that causes problems even more frequently than the restricted
productions issue.

   var a = 1;
   var b = 2;
   var c = { foo : "bar" }
   [a, b].forEach(alert); // cannot call method 'forEach' of undefined

A "disable ASI" pragma will not catch this error.  No ASI occurred!

In my years writing JavaScript, I can count on one finger the number
of times that restricted production ASI has bitten me.  I immediately
abandoned the Allman style in favor of a BSD-KNF
brace-goes-with-the-start-thing style, and all was well with the
world.  This no longer looked strange to me:

   return {
     foo : "bar"
   };

I can also count on one finger the number of restricted productions
where this is an issue: throw will issue a syntax error, since the
expression is not optional, and named continue/break are very rare.

However, the "non-ASI" error above (where there is a \n followed by a
[, (, +, etc) bites a *lot*, and is almost impossible to see when
parsing the code with human eyes and brains.

The proliferation of ; is not a keyboard-tax.  It is an
eyeball/brain-tax.  "Why complain about semicolons?  You don't even
see them."  That's why.  Because I want to see the relevant parts of
my code.  If you put them on every line, and worse, at the
jagged-right edge of the line,

The options are to either:

* use a lint step in your development process to catch these issues
(and it's gonna have to be a pretty clever linter to know you didn't
mean to do that)
* adopt a style where such things jump out at you because they look
wrong (as I have done with npm's leading semicolon/comma style), or
* Be Very Careful about using array literals and parenthesized constructions.

I find linters to be somewhat unpleasant housepets, and thus do not
keep them in my own home, though I of course respect their place when
contributing to others' projects, and I have found that Being Very
Careful is not sustainable on teams of 1 or more humans.

Any approach that does not handle the "non-ASI error" case is not a solution.

Every time a warning prints about something that was intended, the
value of warnings is reduced.  That's a bad idea.  In the onclick ASI
example above, printing a warning about the ASI in that code would be
worse than useless.

If we are going to build a less wicked language, and the idea of a
warning-generating pragma seems wise, then we ought to make every
warning as relevant as possible, and not just support
backwards-compatibility, but also do our best to support the intent of
those using the language.  Here's a few situations where (in my
opinion) warnings would be useful:

1. Restricted production followed by \n and an expression which is not
a method or function call, assignment, or function declaration.

   // these would warn:
   return
   { a: b }
   /
   return
       10 + 5

2. Expression followed by \n and a +, (, [, -, *, / at the same indention level.

   // this would warn:
   x = y
   (c + d).print()
   // this would not:
   chain
     ( [some, long, thing]
     , [the, next, chain, link]
     , cb )


--i
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss