Re: function hoisting like var
Ingvar von Schoultz wrote: In theory {{ code }} could be converted to a function that returns information about whatever break/continue/return was reached. But I'd be quite surprised if that is easy. Something like this. Written with syntax sugar: Outer: for (var OutName in OutThing) for (var InName in InThing) {{ break Outer; }} Translation: Outer: for (var OutName in OutThing) { var _Result = (function (_InThing) { for (var InName in _InThing) { return ({JumpSpot: 'break Outer'}) } })(InThing); if (_Result.JumpSpot == 'break Outer') break Outer; } The inner for() is part of the scoping block, so it belongs inside, even though the original code has it above. We must make sure the value of InThing is available inside even if the name is declared for a different variable inside. I use initial underscore to indicate something internal and invisible. It doesn't look complicated here! Unfortunately these things have a terrible tendency to grow in complexity... I now think this could be made very simple. The solution is to make this version slightly limited. Don't support break/continue statements that mention any label outside {{ }}. Leave that for a future version. This simplifies things tremendously! And you don't need that kind of break/continue all that often. (But a future version must include it.) This limited solution only needs break/continue functionality that is already supported. Even the necessary label checking is already supported. An unsupported break such as the following gives a syntax error if you translate {{ }} to a one-shot function: Outer: for (var OutName in OutThing) for (var InName in InThing) {{ break Outer; }} The error message that I get says undefined label, which is misleading, but apart from that it works perfectly. If people find the above limited support for break/continue acceptable for this version, all that remains is the return statement. It seems easiest to use a solution that leaves all the return statements in the original code intact. This makes the translation from {{ }} to function a little elaborate and odd, but everything is nicely contained at one spot. Within the created function, if control reaches the final }}, throw a special error that isn't really an error, rather the opposite, it's a signal that indicates that this is a normal termination. When this signal is received, continue below }}. If instead, within the created function, control reaches a return statement that appears in the original code, the result is a regular return, without the above thrown signal. This indicates that whatever value was returned should be passed along as return value of the enclosing function. This means that {{ }} is essentially translated into this: try { var ReturnValue = (function() { // The code that was written between {{ }} goes here. throw NormalEndSignal; })(); return ReturnValue; } catch (Sig) { if (Sig != NormalEndSignal) throw Sig; } It seems to me that this becomes very nicely contained, very manageable. Implementations will probably want to optimize away this entire elaborate arrangement and replace it with plain and simple scoping blocks. But they can take their time. The above provides the functionality in a simple way. That is, unless I've missed something, and the above solution doesn't work the way I think it does. -- Ingvar von Schoultz --- (My quirky use of capitals in code comes from my opinion that reserved and predefined words should all start with lowercase, and user-defined should all start with uppercase, because this will easily and elegantly prevent a host of name-collision problems when things like programming languages are upgraded with new labels.) ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
How to escape implicit 'with (this)' of a method body
/function foo () { return 'global'; } class bar { function foo () { return 'local'; } function zot () { // How can I call the global foo from here? without (this) { foo(); } } }/ You could use window[foo](); or whatever the global object is named in the environment ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: How to escape implicit 'with (this)' of a method body
On Jul 28, 2008, at 3:22 PM, Michael Haufe wrote: function foo () { return 'global'; } class bar { function foo () { return 'local'; } function zot () { // How can I call the global foo from here? without (this) { foo(); } } } It's the same as if you lambda-coded the above (here shown in JS1.8 [Firefox 3], note the expression closures): function bar() { function foo() 'local'; function zot() global.foo(); } function foo() 'global'; This example uses ES4's global synonym for the global object, but you could capture this in a global var at top level: var global = this; print(new bar().zot()); // print 'global' in ES3 or JS1.8 to get the same effect. You could use window[foo](); or whatever the global object is named in the environment No need to quote and bracket, of course -- window.foo() is fine too. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: How to escape implicit 'with (this)' of a method body
On Jul 28, 2008, at 9:46 PM, Brendan Eich wrote: On Jul 28, 2008, at 3:22 PM, Michael Haufe wrote: function foo () { return 'global'; } class bar { function foo () { return 'local'; } function zot () { // How can I call the global foo from here? without (this) { foo(); } } } It's the same as if you lambda-coded the above (here shown in JS1.8 [Firefox 3], note the expression closures): function bar() { function foo() 'local'; function zot() global.foo(); + return {foo: foo, zot: zot}; } function foo() 'global'; This example uses ES4's global synonym for the global object, but you could capture this in a global var at top level: var global = this; print(new bar().zot()); // print 'global' in ES3 or JS1.8 to get the same effect. /be___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: How to escape implicit 'with (this)' of a method body
2008/7/29 Brendan Eich [EMAIL PROTECTED]: On Jul 28, 2008, at 3:22 PM, Michael Haufe wrote: function foo () { return 'global'; } class bar { function foo () { return 'local'; } function zot () { // How can I call the global foo from here? without (this) { foo(); } } } It's the same as if you lambda-coded the above (here shown in JS1.8 [Firefox 3], note the expression closures): function bar() { function foo() 'local'; function zot() global.foo(); } function foo() 'global'; This example uses ES4's global synonym for the global object, but you could capture this in a global var at top level: var global = this; print(new bar().zot()); // print 'global' in ES3 or JS1.8 to get the same effect. You could use window[foo](); or whatever the global object is named in the environment No need to quote and bracket, of course -- window.foo() is fine too. /be Isn't the 'with' statement in the original example significant? In the general case, assuming that you don't know what properties 'this' has (as it may have dynamic properties in addition to the fixtures determined by its class), you have no way of knowing whether 'global' or 'window' refers to the global object or to some arbitrary property of 'this.' -Jon ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: How to escape implicit 'with (this)' of a method body
On Jul 28, 2008, at 10:05 PM, Jon Zeppieri wrote: Isn't the 'with' statement in the original example significant? In the general case, assuming that you don't know what properties 'this' has (as it may have dynamic properties in addition to the fixtures determined by its class), you have no way of knowing whether 'global' or 'window' refers to the global object or to some arbitrary property of 'this.' The original code used without (this), not with, which I took to mean avoid instance properties shadowing globals. If you read the original as with, then there is no such problem. But if you construct a problematic case using 'with' and dynamic properties, then I concede that 'global' could be shadowed. This is a reason to avoid 'with'. In the ES4 proposals last sent out, you could always use __ES4__::global if you really wanted to avoid conflicts -- unless someone perversely added '__ES4__' as a dynamic instance property. There's no solution to this problem other than reserving at least one name, and we can't do that compatibly. We could reserve __ES4__ in version-selected ES4 mode, but that seems unnecessary. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss