`with` revisited and related to object extension literals

# T.J. Crowder (13 years ago)

All,

I was going to lurk longer before raising this, and apologies if it's been raised before, but the discussion of object extension literals sort of brought it up.

TL;DR: I wonder if the object extension literal might reasonably become a fit-for-purpose with. For years I've thought the with problem could be solved relatively easily by using a leading dot (not an original thought, but I hesitate to even mention where I've seen it before -- VB) and presumably a different keyword. Now I wonder if we don't even need a keyword.

The detail:

The current strawman supports

o.{ a: "foo", b = "bar" };

...where the first is [[DefineOwnProperty]] and the second is [[Put]]. The discussion has moved on a bit with people suggesting using semicolons and allowing calls as well:

o.{ a: "foo"; b = "bar"; c.f(); // e.g., o.c.f() };

or with parens:

o.( a: "foo"; b = "bar"; c.f(); // e.g., o.c.f() );

To me, that starts looking a lot like a series of statements rather than definitions/assignments -- and specifically, a lot like with.

So that leads me to wonder about something along these lines:

o.{ .a: "foo"; // [[DefineOwnProperty]] .b = "bar"; // [[Put]] .c.f(); // E.g., o.c.f(); .d = .a; // E.g., o.d = o.a; .x.{ .y = 2; // E.g., o.x.y = 2; }; };

E.g., a combination of object extension literal and an improved with.

-- T.J.

# T.J. Crowder (13 years ago)

On 31 May 2012 11:33, T.J. Crowder <tj at crowdersoftware.com> wrote:

All,

I was going to lurk longer before raising this, and apologies if it's been raised before, but the discussion of object extension literals sort of brought it up.

TL;DR: I wonder if the object extension literal might reasonably become a fit-for-purpose with. For years I've thought the with problem could be solved relatively easily by using a leading dot (not an original thought, but I hesitate to even mention where I've seen it before -- VB) and presumably a different keyword. Now I wonder if we don't even need a keyword.

The detail:

The current strawman supports

o.{ a: "foo", b = "bar" };

...where the first is [[DefineOwnProperty]] and the second is [[Put]]. The discussion has moved on a bit with people suggesting using semicolons and allowing calls as well:

o.{ a: "foo"; b = "bar"; c.f(); // e.g., o.c.f() };

or with parens:

o.( a: "foo"; b = "bar"; c.f(); // e.g., o.c.f() );

To me, that starts looking a lot like a series of statements rather than definitions/assignments -- and specifically, a lot like with.

So that leads me to wonder about something along these lines:

o.{ .a: "foo"; // [[DefineOwnProperty]] .b = "bar"; // [[Put]] .c.f(); // E.g., o.c.f(); .d = .a; // E.g., o.d = o.a; .x.{ .y = 2; // E.g., o.x.y = 2; }; };

E.g., a combination of object extension literal and an improved with.

-- T.J.

Sorry, a couple of points I should have made about the above:

  1. I used {} rather than () because this is a block (thus let works within it).

  2. I originally envisioned this as a statement (of course, I was originally thinking we'd have a new keyword, until the object extension literal discussion), but it could be an expression; if so, presumably the result of the expression would be the object.

  3. The leading dot makes tools support a bit simpler.

  4. The leading dot seems, to me, to be more explicit than just having the first symbol on the left being implicitly a property the object. EIBTI

  5. There would be a temptation to try to backfit this on object initializers as well, but I'd be worried about the confusion it creates (not least for parsers) supporting both syntaxes within an object initializer. If this new thing is an expression (see #2), there's no need, because o = {}.{ .a = 5; .b = .a; }; works just fine.

-- T.J.

# Andreas Rossberg (13 years ago)

On 31 May 2012 12:52, T.J. Crowder <tj at crowdersoftware.com> wrote:

  1. I originally envisioned this as a statement (of course, I was originally thinking we'd have a new keyword, until the object extension literal discussion), but it could be an expression; if so, presumably the result of the expression would be the object.

Note that, if this is an expression, then you are introducing a variant of do'-expressions through the backdoor (i.e., a way to nest statements into expressions). That is a significant change to the language, so it only is an option if we agree to havedo'.

  1. The leading dot seems, to me, to be more explicit than just having the first symbol on the left being implicitly a property the object. EIBTI

I agree with that.

# T.J. Crowder (13 years ago)

On 31 May 2012 12:12, Andreas Rossberg <rossberg at google.com> wrote:

On 31 May 2012 12:52, T.J. Crowder <tj at crowdersoftware.com> wrote:

  1. I originally envisioned this as a statement (of course, I was originally thinking we'd have a new keyword, until the object extension literal discussion), but it could be an expression; if so, presumably the result of the expression would be the object.

Note that, if this is an expression, then you are introducing a variant of do'-expressions through the backdoor (i.e., a way to nest statements into expressions). That is a significant change to the language, so it only is an option if we agree to havedo'.

Indeed, though unintentionally. I think the two are closely related, but can be decided individually. FWIW, I have no strong opinion (not that matters!) on whether these should be expressions. Those who are deeper in the process can speak to that question rather more usefully than I. I do kind of like how them being expressions bypasses the question of extending object initializer syntax possibly past the breaking point (my #5).

-- T.J.

# David Herman (13 years ago)

On May 31, 2012, at 4:12 AM, Andreas Rossberg wrote:

  1. The leading dot seems, to me, to be more explicit than just having the first symbol on the left being implicitly a property the object. EIBTI

I agree with that.

As I said in another thread, it's not going to happen because of the ASI hazard.

# T.J. Crowder (13 years ago)

On 31 May 2012 19:24, David Herman <dherman at mozilla.com> wrote:

On May 31, 2012, at 4:12 AM, Andreas Rossberg wrote:

  1. The leading dot seems, to me, to be more explicit than just having the

first symbol on the left being implicitly a property the object. EIBTI

I agree with that.

As I said in another thread, it's not going to happen because of the ASI hazard.

Dave

Expand/link? How does this cause an ASI issue (that can't be solved)?

-- T.J.

# Rick Waldron (13 years ago)

On Thu, May 31, 2012 at 4:46 PM, T.J. Crowder <tj at crowdersoftware.com>wrote:

On 31 May 2012 19:24, David Herman <dherman at mozilla.com> wrote:

As I said in another thread, it's not going to happen because of the ASI hazard.

Dave

Expand/link? How does this cause an ASI issue (that can't be solved)?

I believe Dave is referring to this thread: www.mail-archive.com/[email protected]/msg16071.html

# T.J. Crowder (13 years ago)

On 31 May 2012 22:17, Rick Waldron <waldron.rick at gmail.com> wrote:

On Thu, May 31, 2012 at 4:46 PM, T.J. Crowder <tj at crowdersoftware.com>wrote:

On 31 May 2012 19:24, David Herman <dherman at mozilla.com> wrote:

As I said in another thread, it's not going to happen because of the ASI hazard.

Dave

Expand/link? How does this cause an ASI issue (that can't be solved)?

I believe Dave is referring to this thread: www.mail-archive.com/[email protected]/msg16071.html

-- T.J.

Thanks Rick. For lurkers:

o.{ foo() // No semi .bar() // Is this o.bar()? or .bar() on the result of foo()? };

So we solve that, which is easily done. Could be ~. or .. or any of several other things, such as:

o.{ ~.a: "foo"; // [[DefineOwnProperty]] ~.b = "bar"; // [[Put]] ~.c.f(); // E.g., o.c.f(); ~.d = ~.a; // E.g., o.d = o.a; ~.x.{ ~.y = 2; // E.g., o.x.y = 2; }; };

Still offers all the benefits listed earlier, and in fact is possibly even more explicit. For ~. read any reasonably combination of symbols that we can make work syntactically.

The precise syntax is not as important as the concept. Basically, it seems to me that object extension literals are really just a limited and implicit with, so rather than trying to solve a limited and implicit with, we should either solve the syntactic issues around a genuine, 21st-century explicit with that encompasses those same use cases, or the whole thing (improved with and object literal extensions) isn't worth bothering with (which is a real possibility).

-- T.J.

# Rick Waldron (13 years ago)

Thanks Rick. For lurkers:

o.{ foo() // No semi .bar() // Is this o.bar()? or .bar() on the result of foo()? };

I've been following and have read back in the thread, but I'm not seeing a how ".bar()" would be allowed?

Point me in the right direction!

# Brendan Eich (13 years ago)

Rick Waldron wrote:

Thanks Rick. For lurkers:

o.{
    foo()  // No semi
    .bar() // Is this o.bar()? or .bar() on the result of foo()?
};

I've been following and have read back in the thread, but I'm not seeing a how ".bar()" would be allowed?

In the with example that Dave gave:

 with (obj) {
     foo() // no semi
     .bar = 12
 }

it's all allowed as in no syntax error (to correct via ASI) and no restricted production (to make line termination significant).

Over the years people have suggested reforming 'with' a la VB by requiring leading . before names meant to be looked up in the 'with' object instead of the scope chain. But that fails as Dave showed.

T.J. was suggesting that Dave's cascade proposal has the 'with' hazard, but it doesn't. No scope chain lookup. Therefore no need for leading ., ~. or any such noise.

# T.J. Crowder (13 years ago)

On 1 June 2012 00:28, Brendan Eich <brendan at mozilla.org> wrote:

In the with example that Dave gave:

with (obj) { foo() // no semi .bar = 12 }

it's all allowed as in no syntax error (to correct via ASI) and no restricted production (to make line termination significant).

Over the years people have suggested reforming 'with' a la VB by requiring leading . before names meant to be looked up in the 'with' object instead of the scope chain. But that fails as Dave showed.

T.J. was suggesting that Dave's cascade proposal has the 'with' hazard, but it doesn't. No scope chain lookup. Therefore no need for leading ., ~. or any such noise.

/be

What is "Dave's cascade proposal"? You mean throwing function calls into the existing object extension literal? Or...?

I'd appreciate it if characterizations like "noise" were done...carefully. We're all here because we love JS and want to improve it and move it forward.

Thanks,

-- T.J.

# Brendan Eich (13 years ago)

T.J. Crowder wrote:

On 1 June 2012 00:28, Brendan Eich <brendan at mozilla.org <mailto:brendan at mozilla.org>> wrote:

In the with example that Dave gave:

   with (obj) {
       foo() // no semi
       .bar = 12
   }


it's all allowed as in no syntax error (to correct via ASI) and no
restricted production (to make line termination significant).

Over the years people have suggested reforming 'with' a la VB by
requiring leading . before names meant to be looked up in the
'with' object instead of the scope chain. But that fails as Dave
showed.

T.J. was suggesting that Dave's cascade proposal has the 'with'
hazard, but it doesn't. No scope chain lookup. Therefore no need
for leading ., ~. or any such noise.

/be

What is "Dave's cascade proposal"? You mean throwing function calls into the existing object extension literal? Or...?

Dave's cascade proposal:

blog.mozilla.org/dherman/2011/12/01/now-thats-a-nice-stache

I'd appreciate it if characterizations like "noise" were done...carefully. We're all here because we love JS and want to improve it and move it forward.

No offense -- I called leading . noise too (and I've toyed with it as somehow helping 'with' if forbidden at start of line, e.g.).

I believe it's a mistake to theory-patch, however. You were following the reform-with path which leads to leading dot. Then the ASI (lack of it, as usual -- "nega-ASI" :-P) problem reared its head. Then you mooted ~. This approach has a smell, in science and engineering. I say this without meaning offense again, since I've done it myself (especially in code, so there's a code patch too -- and technical debt if not a user-facing "noise" spike).

# T.J. Crowder (13 years ago)

On 1 June 2012 00:51, Brendan Eich <brendan at mozilla.org> wrote:

Dave's cascade proposal:

blog.mozilla.org/**dherman/2011/12/01/now-thats-**a-nice-stacheblog.mozilla.org/dherman/2011/12/01/now-thats-a-nice-stache

Thanks. With a great deal of respect, I'm not seeing how that isn't "with-lite" with a magic LHS. Indeed, how is it less confusing (and less implicit) than the existing with? Re the recurring array example: Which pop is it? One specific to the object? A local? Something in the containing scope? A global? Why is the magic constrained to the LHS?

I believe it's a mistake to theory-patch, however. You were following the

reform-with path which leads to leading dot. Then the ASI (lack of it, as usual -- "nega-ASI" :-P) problem reared its head. Then you mooted ~. This approach has a smell, in science and engineering. I say this without meaning offense again, since I've done it myself (especially in code, so there's a code patch too -- and technical debt if not a user-facing "noise" spike).

I'm not seeing (smelling?) a smell. Making free symbols be implicit property lookups has an error-prone history (vis: with as-was), so my thought was: Make it explicit. I'm not by far the first. Dave pointed out that ASI causes an issue with the specific syntax I mentioned, so I addressed that -- while making the point that the specific syntax was not the main thrust of the argument. Surely we can respond to reasonable syntactic flags without invalidating the broader concept?

All of which is somewhat beside the point. The main point is that it seems like the object extension literal proposal (esp. when combined with the cascade proposal) is another form of with, with similar issues, plus some confusion with object initializers. My main point is: Perhaps the issues arising are in part because of the magic, and perhaps either A) Making it explicit helps, or B) The magic ain't worth it.

Let's take another look:

var foo = "bar";

this.{ foo = "baz" yow = "hello" baz = foo };

What's foo? Is it still "bar" or is it "baz"? What's this.baz? Is it "bar" or "baz" or did the code throw or...? Contrast with:

var foo = "bar";

this.{ ~.foo = "baz"; ~.yow = "hello"; ~.baz = foo; };

EIBTI. No confusion between foo and ~.foo. There's a distinction between being explicit, being clear, and adding noise.

Again I want to emphasize that the precise syntax is not the point. It could be "~" or ">" or "^" or any of several other things instead of "~". (I quite like the ~, though, as it happens.) Being explicit, and deciding to either do, or not do, with-lite, is the point.

(And I want to emphasize that I'm clear I'm a newcomer amongst giants, although not remotely a newcomer to designing solutions; and I have a lot of respect for the giants in the room. Just trying to contribute, to be helpful; not to be difficult.)

-- T.J.

# Brendan Eich (13 years ago)

T.J. Crowder wrote:

On 1 June 2012 00:51, Brendan Eich <brendan at mozilla.org <mailto:brendan at mozilla.org>> wrote:

Dave's cascade proposal:

http://blog.mozilla.org/dherman/2011/12/01/now-thats-a-nice-stache/

Thanks. With a great deal of respect, I'm not seeing how that isn't "with-lite" with a magic LHS. Indeed, how is it less confusing (and less implicit) than the existing with? Re the recurring array example: Which pop is it? One specific to the object?

Yes, and only that.

A local?

No. This is a special form, the expressions you can cascade in the {} are restricted. The leading identifier is always only a property reference in the head object.

Something in the containing scope?

Nope.

A global?

No way ;-).

Why is the magic constrained to the LHS?

Because that's the intended useful magic. This is a new special form, as Mark pointed out for factoring

o.foo = 1; o.bar = 2; o.baz()

into

o.{foo = 1; bar = 2; baz()};

(I squished on one line here.)

I believe it's a mistake to theory-patch, however. You were
following the reform-with path which leads to leading dot. Then
the ASI (lack of it, as usual -- "nega-ASI" :-P) problem reared
its head. Then you mooted ~. This approach has a smell, in science
and engineering. I say this without meaning offense again, since
I've done it myself (especially in code, so there's a code patch
too -- and technical debt if not a user-facing "noise" spike).

I'm not seeing (smelling?) a smell.

Theory patching analogue: add a funny but unambiguous character before the . to rescue the reform-with theory. But you agree we're not reforming 'with' and Dave's cascade syntax has nothing to do with 'with' (see above).

Making free symbols be implicit property lookups has an error-prone history (vis: with as-was),

Only if those free symbols are looked up in the scope chain to which the 'with'-head object has been prefixed. There is no hazard in a shorthand derived from good old dot.

so my thought was: Make it explicit. I'm not by far the first. Dave pointed out that ASI causes an issue with the specific syntax I mentioned, so I addressed that -- while making the point that the specific syntax was not the main thrust of the argument. Surely we can respond to reasonable syntactic flags without invalidating the broader concept?

No, we do not agree on what you call the "broader concept". Let's settle that first before syntax arguments.

The theory does not need a ~ patch if there is no 'with' hazard. Dave defined the proposal so that there is not. Are you concerned that there is an appearance of a hazard, due to

obj . { foo = ...

(I spaced things out and left off the right context on purpose). IOW, because if one ignores obj and the dot, we have what looks like a block, which starts with what looks like a free variable reference, foo?

I get that. It's why I argued for () instead of {}. But this is a readability or usability issue, so again I wouldn't try patching with leading ~. under the {} bracketing. And note that it's not a 'with'-like situation in any case -- no scope chain lookup (only what might be the appearance of that).

All of which is somewhat beside the point. The main point is that it seems like the object extension literal proposal (esp. when combined with the cascade proposal) is another form of with, with similar issues, plus some confusion with object initializers.

Let's be precise. You keep bringing 'with' up but it's not relevant to the cascade proposal, going by Dave's definitions. If you have the "appearance of 'with'" concern I call out above, let's argue about that. It's a good one (again it is why I preferred () a day or so ago).

My main point is: Perhaps the issues arising are in part because of the magic, and perhaps either A) Making it explicit helps, or B) The magic ain't worth it. (B) certainly could be the case. Deciding is art not science.

(A) is not constrained to be ~. or any such prefix if the problem is "appearance of 'with'" even thought this new special form was designed not to extend the scope chain. We should argue about the predicate problem, not about explicit patches to fix it.

# T.J. Crowder (13 years ago)

On 1 June 2012 01:40, Brendan Eich <brendan at mozilla.org> wrote:

Let's be precise. You keep bringing 'with' up but it's not relevant to the cascade proposal, going by Dave's definitions. If you have the "appearance of 'with'" concern I call out above, let's argue about that. It's a good one (again it is why I preferred () a day or so ago).

Yes, that's my concern. Something that looks almost exactly like the old with, complete with implicit magic free symbol resolution, worries me. I "keep" bringing up with because it's implicit in the proposals. It's not something I'm adding, I'm just shining a light on it. This is more true of the cascade than object extension literals, but the inclusion of things that look like assignments in object extension literals makes it true of them as well.

The only place that immediately comes to mind where free symbols aren't currently resolved relative to the scope chain is the property name literals in object initializers, and they have a sufficiently distinct syntax (using the colon) that they're fairly distinct.

Separating the two distinct things (extension literals and cascade) out:

Object extension literals:

var a = "foo"; o.{ a = "bar" };

The lack of any kind of qualifier on the a makes it problematic, to my mind. Yes, there's that special .{ ... } syntax, but it's at a sufficient remove from the assignment that it's asking for trouble. Perhaps this could be solved without a with-like structure by using something other than =, to maintain the distinct nature that object initializers have. E.g.,

var a = "foo"; o.{ a: "bar", // [[DefineOwnProperty]] b:= "baz" // [[Put]] };

Now it doesn't look like an assignment any more. It echoes object initializer syntax. You could even read := as "define or put". And it has the advantage it could be harmlessly back-fitted on object initializers (er, I think -- I'm not a grammar god like AWB).

Now the cascade:

array.{ pop() pop() };

That looks like with, it acts like with, and it seems to have the same motivation as with: To avoid writing array repeatedly. (I'm with Dave on his point about the fragility of function chaining, btw.) I understand that the proposal for it says pop must be resolved relative to array (unlike with, where it could be anywhere on the scope chain), but it's just way too similar. If we're going to do with, let's do it. I might want to avoid writing array repeatedly on the RHS, too. (No RHSs in the above, granted.)

Anyway, faced with two proposals with with-like features, it seemed reasonable to point that out, to suggest how the issues with both could be resolved with an explicit form of with. I'm a big fan of explicitness, and a big fan of using a single solution to address multiple goals. But it's just one way to go.

-- T.J.

# David Herman (13 years ago)

On May 31, 2012, at 5:30 PM, T.J. Crowder wrote:

On 1 June 2012 00:51, Brendan Eich <brendan at mozilla.org> wrote: Dave's cascade proposal:

blog.mozilla.org/dherman/2011/12/01/now-thats-a-nice-stache

Thanks. With a great deal of respect, I'm not seeing how that isn't "with-lite" with a magic LHS.

There's no magic at all. The LHS is not an expression; there's no variable resolution involved. The problem with with is that it captures all variable lookups anywhere in any nested expression. That's not the case with the cascade proposal. Furthermore, with injects an object into the scope chain, so a variable lookup might end up either on the object or elsewhere in the scope chain. Again, not the case here. You can always tell statically which parts of the syntax correspond to the object and which things are just variables.

I'm not saying I'm 100% enthusiastic about the cascade proposal as is. In fact, I think we're wasting a ton of time on this area when we have more important things to work on. And no form of mustache is happening in ES6 anyway. It's been demoted to strawman; it never had consensus; it's not fully baked.

Indeed, how is it less confusing (and less implicit) than the existing with? Re the recurring array example: Which pop is it? One specific to the object? A local? Something in the containing scope? A global? Why is the magic constrained to the LHS?

There is no mixing of scope and object lookup in the cascade proposal. None at all.

I'm not seeing (smelling?) a smell. Making free symbols be implicit property lookups has an error-prone history (vis: with as-was), so my thought was: Make it explicit. I'm not by far the first. Dave pointed out that ASI causes an issue with the specific syntax I mentioned, so I addressed that -- while making the point that the specific syntax was not the main thrust of the argument. Surely we can respond to reasonable syntactic flags without invalidating the broader concept?

What Brendan is saying is that the cascades proposal does address the broader concept: being able to multiple property accesses without having to rename the target object, and in a way that doesn't defeat lexical scope. Now, you proposed a syntax that doesn't work because of ASI. Then you tossed in a ~ to address that. Sorry, but you don't design syntax by throwing more sigils at it till it's unambiguous. That way lies line noise.

All of which is somewhat beside the point. The main point is that it seems like the object extension literal proposal (esp. when combined with the cascade proposal) is another form of with,

No, it's just not. There are valid issues with all the variations on "mustache," but "being another form of with" is not one of them. Some good objections have been raised on this thread:

https://gist.github.com/9a6d60e9c15ac4239b3d

But the problem with with is that it screws up lexical scope. None of the mustache proposals, including the cascades one, screws up lexical scope.

Again I want to emphasize that the precise syntax is not the point. It could be "~" or ">" or "^" or any of several other things instead of "~". (I quite like the ~, though, as it happens.) Being explicit, and deciding to either do, or not do, with-lite, is the point.

Just please stop saying that it's like with. It's totally unlike with, and you'll only confuse people by saying it is. I'm not sure if you've understood the intended semantics, but it's simply nothing like with. You can disagree with the feature, but stick to technically valid arguments.

(And I want to emphasize that I'm clear I'm a newcomer amongst giants, although not remotely a newcomer to designing solutions; and I have a lot of respect for the giants in the room. Just trying to contribute, to be helpful; not to be difficult.)

Hey, no stress -- always happy to have input. Just please, no more bogus comparisons to with.

# David Herman (13 years ago)

On May 31, 2012, at 7:08 PM, T.J. Crowder wrote:

On 1 June 2012 01:40, Brendan Eich <brendan at mozilla.org> wrote: Let's be precise. You keep bringing 'with' up but it's not relevant to the cascade proposal, going by Dave's definitions. If you have the "appearance of 'with'" concern I call out above, let's argue about that. It's a good one (again it is why I preferred () a day or so ago).

Yes, that's my concern. Something that looks almost exactly like the old with, complete with implicit magic free symbol resolution, worries me. I "keep" bringing up with because it's implicit in the proposals. It's not something I'm adding, I'm just shining a light on it.

This is a misunderstanding. There's no such thing as "free symbol resolution." There are "free variables" and there is "variable resolution" but "free symbol resolution" doesn't mean anything.

In the cascade proposal, the LHS of each item contains no variables. It's just a property name used on the target object. There's never any ambiguity as to whether it might be looked up on the object or looked up in the lexical environment.

The RHS of each assignment is just an ordinary expression, and is looked up in the ordinary lexical environment.

This is nothing like with. Your protestations are generating more heat than light.

This is more true of the cascade than object extension literals, but the inclusion of things that look like assignments in object extension literals makes it true of them as well.

Absolutely not. You can argue that the cascade syntax is more confusing -- and it may well be -- but semantically it's totally the same as the other mustache proposals (other than the additional ability to call methods as well, but that also introduces no semantic issues with scope).

Now the cascade:

array.{ pop() pop() };

That looks like with, it acts like with,

No, it doesn't, and it would be really helpful if you would try to understand why it doesn't.

# Brendan Eich (13 years ago)

T.J. Crowder wrote:

On 1 June 2012 01:40, Brendan Eich <brendan at mozilla.org <mailto:brendan at mozilla.org>> wrote:

Let's be precise. You keep bringing 'with' up but it's not
relevant to the cascade proposal, going by Dave's definitions. If
you have the "appearance of 'with'" concern I call out above,
let's argue about that. It's a good one (again it is why I
preferred () a day or so ago).

Yes, that's my concern. Something that looks almost exactly like the old with, complete with implicit magic free symbol resolution, worries me. I "keep" bringing up with because it's implicit in the proposals. It's not something I'm adding, I'm just shining a light on it.

No, you're just rehashing a concern based on appearances. Operationally there is nothing 'with'-like in cascades. Please stop asserting more than "looks" by adding semantic nonsense such as "complete with implicit magic free symbol resolution".

# Brendan Eich (13 years ago)

David Herman wrote:

Now the cascade:

array.{ pop() pop() };

That looks like with, it acts like with,

No, it doesn't, and it would be really helpful if you would try to understand why it doesn't.

So the key here is prototype chain vs. scope chain. 'with' extends the scope chain:

with (array) { pop() pop() };

so the two chains look like this:

 Object.prototype <---------------+
       ^                           \
       |                            \

Array.prototype : ^ : | | HEAD -> array -- next-outer-scope --> global

where HEAD is the head of the scope chain. The [[Prototype]]-linked chain points upward, the scope chain left-to-right. Of course there is no next-outer-scope intrinsic property of array, that would make a pigeon-hole problem (with (array) (function () { with (array) {...} }), e.g.)

Cascades do nothing to the scope chain and desugar

array.{ pop() pop() };

to

array.pop(); array.pop();

For the example, with pop the method on Array.prototype, of course there is no difference. Even if a custom 'pop' property were added to just array, shadowing Array.prototype.pop, no difference. But the crucial difference is when array is not even an array, or there's a typo:

array.{ pop() flop() };

Unlike the 'with' case, flop() in the cascade is desugared to array.flop(), so there's a type error trying to invoke the undefined value, absent any 'flop'-named property with a callable value in array itself, or on its prototype chain.

In the 'with' case, a global

var flop = function () { return "haha"; }

assigned before the 'with' will make the equivalent 'with'-based code compile and run -- but probably not as intended.

This may seem not much of a difference, but it's major not only due to the typo and array-not-an-Array-instance cases. The scope chain extension is costly and forces deoptimization in common implementations. And of course 'with' is banned in strict mode.

Dave, any other differences to spell out?

# David Herman (13 years ago)

On May 31, 2012, at 9:31 PM, Brendan Eich wrote:

This may seem not much of a difference, but it's major not only due to the typo and array-not-an-Array-instance cases. The scope chain extension is costly and forces deoptimization in common implementations. And of course 'with' is banned in strict mode.

Dave, any other differences to spell out?

That's pretty much it, but I'd also point out one more important consequence: by with adding an object to the scope chain, it pollutes scope with potentially unintended properties of the object -- or any of its prototypes. So when you have a variable reference in a sub-expression, you may think you know what it refers to but it could be captured by the with object or one of its properties.

var obj = {
    log: console.log.bind(console),
    foo: function() { Object.prototype.bar = "captured" }
};
var bar = "local variable";
with (obj) {
    log(bar); // local variable
    foo();
    log(bar); // captured
}

Whereas with cascades, you'd get:

var obj = {
    log: console.log.bind(console),
    foo: function() { Object.prototype.bar = "captured" }
};
var bar = "local variable";
with (obj) {
    log(bar); // local variable
    foo();
    log(bar); // local variable
}
# David Herman (13 years ago)

On May 31, 2012, at 9:50 PM, David Herman wrote:

...but it could be captured by the with object or one of its properties.

s/properties/prototypes/

# David Herman (13 years ago)

On May 31, 2012, at 9:50 PM, David Herman wrote:

Whereas with cascades, you'd get:

var obj = { log: console.log.bind(console), foo: function() { Object.prototype.bar = "captured" } }; var bar = "local variable"; with (obj) { log(bar); // local variable foo(); log(bar); // local variable }

Oh for crying out loud. Of course I meant:

var obj = {
    log: console.log.bind(console),
    foo: function() { Object.prototype.bar = "captured" }
};
var bar = "local variable";
obj.{
    log(bar); // local variable
    foo();
    log(bar); // captured
}
# Brendan Eich (13 years ago)

Right, that capture-in-prototype case does not differ due to both cascade desugaring and 'with' searching the head object including its prototype chain.

But with a deeper scope chain, and bar not bound in the innermost scope, then 'with' allows an evil interloping function to shadow (or delete if configurable) along the scope chain.

# Brendan Eich (13 years ago)

Brendan Eich wrote:

you're just rehashing a concern based on appearances

which (I want to be clear; sorry for harshing on the 'with' point) is a valid concern. We should discuss it directly, no 'with'-semantics mixed in.

# T.J. Crowder (13 years ago)

On 1 June 2012 03:23, David Herman <dherman at mozilla.com> wrote:

There is no mixing of scope and object lookup in the cascade proposal. None at all.

You're talking the technical details. I'm talking appearance and expectation in the eyes of developers.

Just please stop saying that it's like with. It's totally unlike with, and you'll only confuse people by saying it is. I'm not sure if you've understood the intended semantics, but it's simply nothing like with. You can disagree with the feature, but stick to technically valid arguments.

....

Hey, no stress -- always happy to have input. Just please, no more bogus comparisons to with.

Could we please avoid derogatory terms like "bogus"? I'm talking about what people see when they look at code (more below). That's a valid argument. You can disagree with it without deriding it.

You're quite right that I shouldn't have said it acts like with, because of course, it's been clearly defined not to. I should have said that it looks like it acts like it, or just better yet just stuck with "looks." Sorry, it was late.

On 1 June 2012 03:30, David Herman <dherman at mozilla.com> wrote:

This is a misunderstanding. There's no such thing as "free symbol resolution." There are "free variables" and there is "variable resolution" but "free symbol resolution" doesn't mean anything.

I should have said "token", or possibly "identifier," not "symbol".

In the cascade proposal, the LHS of each item contains no variables.

I didn't say it did.

Now the cascade:

array.{ pop() pop() };

That looks like with, it acts like with,

No, it doesn't, and it would be really helpful if you would try to understand why it doesn't.

I do understand how you want it to work, how you've defined it. I'm clear on that: The identifiers are property names, looked up on the object in question in the usual way; they are not to be resolved by the scope chain. A freestanding foo outside the mustache is completely unrelated to a freestanding foo within the mustache. I get it.

I'm saying that's not what I see when I look at it, and not what I think most developers will see, because -- and correct me if I'm wrong, it's certainly been known! -- the only other place where that's true is an object initializer, isn't it? I believe everywhere else, an identifier that isn't a reserved word, standing free, is resolved via the scope chain. Object initializers look enough unlike step-by-step code (even though they are processed in source order) that they aren't confusing.

Apologies for apparently having given the impression I didn't understand how you defined cascades to work. We could have avoided some wasted time if I'd made that clear.

If the cascade proposal is not going forward in its current form any time soon, let's shelve this conversation. Bigger fish to fry, as you said. If you'd like the final word, though, I'm happy for you to have it.

-- T.J.

# T.J. Crowder (13 years ago)

On 1 June 2012 06:05, Brendan Eich <brendan at mozilla.org> wrote:

Brendan Eich wrote:

you're just rehashing a concern based on appearances

which (I want to be clear; sorry for harshing on the 'with' point) is a valid concern. We should discuss it directly, no 'with'-semantics mixed in.

/be

Yes, very useful. I'll stick to things like "to me, the syntax makes it look like those identifiers would be resolved via the scope chain" and such. Won't mention with.

I'm a bit worried that people may have thought I was being derisive by talking about with, and that that may have raised hackles. I wasn't. I don't think with is a flawed concept at all (I recognize many do), so I don't use it derisively. I agree with, I think, the majority here including (if I'm not mistaken) your own good self that JS's original with had serious issues, which in my view were down to it using freestanding identifiers, intermixing object property resolution and scope chain resolution. But I have no problem with the concept in a different form.

So in summary and (largely) in closing:

  1. I quite like the idea of the cascade proposal, because like Dave (I think?) I find the way cascades are currently done (a'la jQuery, via return this) less than ideal.

  2. My concerns with it relate to freestanding identifiers and how that looks. See earlier note to Dave.

  3. I think that concern can be dealt with without going to a with-like structure.

  4. I also think they could be dealt with via a new with-like structure that did not put an object at the top of the scope chain, but instead introduced a placeholder token for the object reference as purely syntactic sugar (~. or similar). To me there's a lot of use there, including cascades. But I seem to be alone. :-) I find that a bit odd, given how similar to that the goals of the cascade sugar seem to be, but if I'm on my own, I'm on my own.

Best,

-- T.J.

# Aymeric Vitte (13 years ago)

No, you are not alone.

Mustache and cascade are interesting but maybe not extremely, extremely usefull.

Then as people have tried since years, I did write too a 'with'-like proposal in strict mode, I already sent it some time ago and got 0 feedback, maybe I did not present it the right way, it has almost nothing to do with the usual 'with' (which I find so strange that could never figure out how this could be used), it's somewhere the contrary, the concept is about the ability of binding things simply, not about making incredible mix-up of accessing/defining properties/var/bindings,
so here it is again, not sure it can fit what you want but I have added more examples to show what it could simplify, and changed the title, it's not a 'with' revival, but a 'with' redesign, and then if 'with' is confusing (or not liked) it can be called another name :

gist.github.com/edd064e5b29e67ebe493

It's a modest 'essai' (perfectible, maybe containing wrong or impossible things) so if it has to be destroyed, please be a little indulgent, at least I don't think one could say that the concepts behind it are not (very) usefull.

Le 01/06/2012 12:09, T.J. Crowder a écrit :

# David Herman (13 years ago)

On Jun 1, 2012, at 2:54 AM, T.J. Crowder wrote:

Hey, no stress -- always happy to have input. Just please, no more bogus comparisons to with.

Could we please avoid derogatory terms like "bogus"? I'm talking about what people see when they look at code (more below). That's a valid argument. You can disagree with it without deriding it.

Not deriding; it wasn't clear to me that your argument had to do with perception rather than semantics. I was responding to the words you said ("that's with-lite", "acts like with"). I was trying to be friendly, and failed -- where I come from "bogus" is not derogatory, it just means "invalid" without being debate-club nerdcore. And I do take issue with the analogy to with. But I apologize for coming down too hard. These memes spread easily and they spread fast, so I really wanted to head off any confusion that we would ever specify something like with.

In the cascade proposal, the LHS of each item contains no variables. I didn't say it did.

It was your use of the word "free" that confused me -- see below...

A freestanding foo outside the mustache is completely unrelated to a freestanding foo within the mustache. I get it.

Fair enough!

I'm saying that's not what I see when I look at it, and not what I think most developers will see, because -- and correct me if I'm wrong, it's certainly been known! -- the only other place where that's true is an object initializer, isn't it? I believe everywhere else, an identifier that isn't a reserved word, standing free, is resolved via the scope chain.

Oh, you're using "free" in a different way than I'm accustomed to. (A "free variable" is a variable reference that is not bound, or not bound in a particular context.) That's part of what threw me off.

So yeah, your objection is similar to Mikeal Rogers' objection in the gist thread I linked to before:

https://gist.github.com/9a6d60e9c15ac4239b3d#gistcomment-337536

I actually agree with that. The issue here is that to understand that the LHS of each item corresponds to the object rather than scope, you have to figure out that you're underneath a mustache. That's a reasonable objection.

I just take issue with the over-broad analogy to with. The problem with with is that it's statically undecidable whether any variable in the body is bound by the object or by something else in the scope chain.

Apologies for apparently having given the impression I didn't understand how you defined cascades to work. We could have avoided some wasted time if I'd made that clear.

And I apologize for reacting so strongly. It's just that with is anathema to many JS developers (for good reason!), and it's an easy smear that gets used loosely to disregard proposals or even ES6 writ large.

# T.J. Crowder (13 years ago)

On 1 June 2012 18:02, David Herman <dherman at mozilla.com> wrote:

I just take issue with the over-broad analogy to with. The problem with with is that it's statically undecidable whether any variable in the body is bound by the object or by something else in the scope chain.

Yeah, at least, it is with JS's current with.

And I apologize for reacting so strongly. It's just that with is anathema to many JS developers (for good reason!), and it's an easy smear that gets used loosely to disregard proposals or even ES6 writ large.

Yes, sorry, I was very slow to pick up on that connotation (I don't share a negative view of with as a concept; I agree about the issues with JS's old/current with and never use it because of them). The penny finally dropped when I was replying later to Brendan. Talk about causing inadvertent offense.

Anyway, all clear now, and thanks again for listening!

-- T.J.

# Brendan Eich (13 years ago)

T.J. Crowder wrote:

On 1 June 2012 18:02, David Herman <dherman at mozilla.com <mailto:dherman at mozilla.com>> wrote:

I just take issue with the over-broad analogy to `with`. The
problem with `with` is that it's statically undecidable whether
any variable in the body is bound by the object or by something
else in the scope chain.

Yeah, at least, it is with JS's current with.

And I apologize for reacting so strongly. It's just that `with` is
anathema to many JS developers (for good reason!), and it's an
easy smear that gets used loosely to disregard proposals or even
ES6 writ large.

Yes, sorry, I was very slow to pick up on that connotation (I don't share a negative view of with as a concept; I agree about the issues with JS's old/current with and never use it because of them). The penny finally dropped when I was replying later to Brendan. Talk about causing inadvertent offense.

Anyway, all clear now, and thanks again for listening!

Thanks for writing -- I think between your point about the left-hand sides embedded in a cascade looking "free" and Mikeal's point on the gist Dave cited, I am not whole-hog in favor of cascades.

It's good to thrash such designs in es-discuss and see if we can get to something promising. Cascades have some promise still in my view (Dart went for them) but they also seem marginal, in the YAGNI sense, and they add comprehension complexity and therefore (for some) confusion about what's being assigned.

I wouldn't try to rescue them with LHS prefixes. Among other reasons I think TC39 and the large anti-grawlix crowd won't go for any such ~.LHS idea.