Re: A simple translation of the scoping-block syntax sugar -- Was: Re: function hoisting like var
The translation can be made simpler. First, define a unique value, to be returned when the end of the scoping block is reached. If done in JavaScript: var _EndOfBlock = {}; Then each {{ }} can be translated to this: var _ReturnValue = (function (arguments) { // Any governing for(), while() or switch() goes here. { // The code between {{ }} goes here. } return _EndOfBlock; }).call (this, arguments); if (_ReturnValue != _EndOfBlock) return _ReturnValue; Ingvar Ingvar von Schoultz wrote: > The simple translation of {{ }} that I posted yesterday needs > an improvement. It must pass |this| and |arguments| to the scoping > function. > > I still think it looks quite small and simple, and that it would > be a very useful addition to the language. > > try > { var _ReturnValue = (function (arguments) > { > // Any governing for(), while() or switch() goes here. > { > // The code between {{ }} goes here. > } > throw _NormalEndSignal; > }).call (this, arguments); > return _ReturnValue; > } > catch (_Sig) > { > if (_Sig != _NormalEndSignal) > throw _Sig; > } > > We must use .call(), not .apply(), so that we pass the arguments > object as such, with the outer function as arguments.callee. > > In the global scope, |arguments| will be undefined, unless the > programmer has defined it. It should remain undefined inside the > scoping function. > > As an alternative to the above parameter passing, I suppose the > implementation can simply remove the scope function's arguments > object, thereby making the outer arguments object visible. > > Initial underscore means hidden, invisible. > > For a description of the translation, see the quoted text below. > > Ingvar > > > > Ingvar von Schoultz wrote: >> Ingvar von Schoultz wrote: >>> In theory {{ code }} could be converted to a function that >>> returns information about whatever break/continue/return was >>> reached. >> 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 u
Re: A simple translation of the scoping-block syntax sugar -- Was: Re: function hoisting like var
I'd like to summarize some clarifications and arguments. I'm thinking of what it might be like if {{ }} should become available in ES3.1. === Intuitive === The proposed {{ }} mean exactly the same thing as { } in C, Java etc. If switching between languages causes you any difficulties, simply use {{ }} everywhere in your ES3.1 code. This way you get the braces that you're used to from C and Java, apart from a slightly different notation. Think of it as JavaScript having a small difference in brace notation while the functionality is the same. === Control flow === In ES3 you can use { } for plain control flow, without any scoping. This is very useful for small projects. If this is not a good fit for your projects, it's still very useful elsewhere. Please don't deprecate this functionality. For more on the usefulness of this plain control flow, see: https://mail.mozilla.org/pipermail/es4-discuss/2008-July/003353.html === Difference === If you want the full flexibility of using both {{ }} and { }, first decide which type of brace you want to use most in your program. Stick with that almost everywhere. Make an exception only when you have a clear and specific reason, because you need the functionality of the other type. This way your code will be consistent and readable. You can view the {{ }} as containers for variables. Any variable that you declare anywhere will simply splash out of any { } and attach itself to the nearest surrounding {{ }}, becoming visible in the entire space between them. If you prefer a more low-level view, { } are plain jumps and branches, and only {{ }} affect the scope chain. === Ugly === The proposed {{ }} will inevitably look horrible in emails if you use a proportional font such as Times New Roman. Real code is never displayed in such a font. Try a programmer's editor with a suitable font and syntax coloring. It looks completely different! If people still find it ugly, I hope a good alternative can be found, because the functionality would be very useful. === Let declarations === There are existing implementations that support let. My proposal is that /let declarations/ should be completely disabled between {{ }}. This of course includes all { } that are nested between {{ }}. The only reason is simplicity, mainly for the script programmer. Outside {{ }} they should be enabled, for compatibility and to satisfy those who prefer the let and var combination. -- 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
Re: A simple translation of the scoping-block syntax sugar -- Was: Re: function hoisting like var
If the simple translation of {{ }} is used, any governing for(), while() or switch() must be moved inside the scoping function. A very simple, very minimalistic approach may be enough. for (var Name in Thing) {{ }} Name is locally contained inside {{ }} while Thing is outside. But maybe the compiler doesn't have to make this distinction. Personally I'd never use the same name with different meanings so close together, like this: var Thing = ...; for (var Name in Thing) {{ var Thing = ...; }} I find that obscure and error-prone. If the limitation is acceptable, a very minimalistic translation of {{ }} could simply move the entire for (...) inside the scoping function, and leave it at that. As long as Thing isn't redeclared inside, the outer Thing is visible and it works. Does this make it simple enough for ES3.1? As an added bonus, the functionality becomes very easy to explain. The rules become very plain and simple. I don't know if a let statement with this limitation would be useful. Every description of let that I can find re-uses names. But if it's useful, it could be trivially implemented as syntax sugar: let (a = x, b = y) {{ }} would be syntax sugar for {{ var a = x, b = y; }} However "let" has different semantics in at least one existing implementation (it does distinguish between same-name variables in the two scopes), so if a minimalistic let is introduced, it should probably use a different keyword. -- 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
A simple translation of the scoping-block syntax sugar -- Was: Re: function hoisting like var
The simple translation of {{ }} that I posted yesterday needs an improvement. It must pass |this| and |arguments| to the scoping function. I still think it looks quite small and simple, and that it would be a very useful addition to the language. try { var _ReturnValue = (function (arguments) { // Any governing for(), while() or switch() goes here. { // The code between {{ }} goes here. } throw _NormalEndSignal; }).call (this, arguments); return _ReturnValue; } catch (_Sig) { if (_Sig != _NormalEndSignal) throw _Sig; } We must use .call(), not .apply(), so that we pass the arguments object as such, with the outer function as arguments.callee. In the global scope, |arguments| will be undefined, unless the programmer has defined it. It should remain undefined inside the scoping function. As an alternative to the above parameter passing, I suppose the implementation can simply remove the scope function's arguments object, thereby making the outer arguments object visible. Initial underscore means hidden, invisible. For a description of the translation, see the quoted text below. Ingvar Ingvar von Schoultz wrote: > Ingvar von Schoultz wrote: >> In theory {{ code }} could be converted to a function that >> returns information about whatever break/continue/return was >> reached. > > 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
Re: Questions about setters
On Jul 29, 2008, at 7:53 AM, P T Withington wrote: >> In AS3 it's like this: >> >> override function set bar (value) { >> super.bar = value; >> } > > So, can I say: > > override function set * (id, value) { There's no such syntax in ES4 as proposed -- the last grammar sent out does not produce * after set in FunctionDefinition^class. The proposal was meta function set(id, value) {...}, and as far as I can see in that proposal, super[id] should work. /be >note('setting ' + id + ' to ' + value); >super[id] = value; > } > > ? (It seems currently, AS3 does not allow `super[]`?) > ___ > 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: Questions about setters
On 2008-07-25, at 05:52EDT, Peter Hall wrote: >> Not sure, but there might be something in the super syntax (eg, >> "super.x >> = 10") that >> would do this. Hasn't been spec'd yet. Not sure what AS3 does. >> > > > In AS3 it's like this: > > override function set bar (value) { > super.bar = value; > } So, can I say: override function set * (id, value) { note('setting ' + id + ' to ' + value); super[id] = value; } ? (It seems currently, AS3 does not allow `super[]`?) ___ 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 2008-07-29, at 01:19EDT, Brendan Eich wrote: > On Jul 28, 2008, at 10:05 PM, Jon Zeppieri wrote: > > The original code used "without (this)", not "with", which I took to > mean "avoid instance properties shadowing globals". Indeed. Perhaps I was being too clever in my pseudo-code. > 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. I guess this is considered a small penalty to pay in exchange for adding the magical instance scope to methods (which O-O programmers seem to expect these days). Something we'd regret more if we had multi-methods, perhaps... ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Defaulting parameters to previous arguments
Will es4 let me say this? function select (start:Number, end:Number=start) { ... } or do I have to resort to something like: function select (start:Number, end:Numer=null) { if (end == null) { end = start; } ... } ___ 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 2008-07-28, at 18:22EDT, 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(); } > } > }/ > > You could use window["foo"](); or whatever the global object is > named in the environment Shouldn't there be an es4 standard way of doing it, without relying on a particular environment? class bar { function foo () { return 'local'; } // I guess this should work, but it seems rather kludgey static function globalfoo (...) { return foo(...); } function zot () { globalfoo(); } ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss