Well we're all discussing radical new syntaxes (I'm looking at you, Ingvar), I might as well propose my own.
One thing about JavaScript that has always really bothered me (and probably several of you) is how JavaScript has opt-in local scope, rather than opt-out local scope. That is, in order to have an identifier reference a local variable, there needs to be a |var| declaration that says that that identifier refers to a local variable, and not non-local one (either in a surrounding function or the global scope). This has a couple related problems: 1) Lack of integrity - in that it's easy to shoot yourself in the foot. One missing |var| and you can be debugging some random error in the wrong place. 2) It's inconvenient. This is pretty self-explanatory. It also encourages the usage of redundant var declarations in often-copied/pasted code, even if it may not be necessary due to var hoisting, which is apparently a practice some people here are not fond of. 3) It can be confusing due to var hoisting. Suppose you have code like this: blah = 10; (function() { print(blah); var blah = 20; print(blah); })(); The novice user would expect this to print "10" followed by "20", when it really prints out "undefined" followed by "20". This has all been discussed to death before, I'm sure, with the conclusion that changing the behavior is backwards incompatible. And I vaguely remember someone saying that we shouldn't add a pragma to "fix" this issue, although the reason for that escapes me at the moment. So here's the proposal that is backwards compatible: provide a block that changes the "default" scoping. var { ... } where everything assigned in ... results in a variable local to that block. Note that this only affects _assignment_. You can still read from a variable from a surrounding scope. As some extra sugar, function name(args) var { ... } would desugar function name(args) { var { ... } } The default scoping setting also nests, i.e. it also crosses function boundaries, so in var { function name(args) { ... } } everything assigned in ... results in a variable local to the functions block. To escape (opt out) of the scoping setting, we need a new keyword. Python 2.5 uses the keyword |nonlocal| for this purpose, so I'll use it as well as a placeholder. var { ... nonlocal x [ = y]; ... } Finally, we can do the same thing for |let|: let { ... } etc. Some examples: --- function list(iterable) { var { if (iterable is Array) { lst = iterable; } else { list = []; for (x in iterable) { lst.push(x); } } } return lst; } function stats(iterable) var { // <-- notice var lst = list(iterable); function calcSum() { sum = 0; for each (x in lst) { sum += x; } } sum = calcSum(); var mean; function calcMean() { nonlocal mean; mean = sum / lst.length; } return [lst.length, sum, mean]; } --- which desugars to: --- function list(iterable) { var lst; if (iterable is Array) { lst = iterable; } else { list = []; for (var x in iterable) { lst.push(x); } } return lst; } function stats(iterable) { var lst = list(iterable); function calcSum() { var sum = 0; for each (var x in lst) { sum += x; } } var sum = calcSum(); var mean = sum / lst.length; return [lst.length, sum, mean]; } --- And finally, it would be nice to have a pragma that can do this for us (again, I don't recall the argument against them). Something like: use scope var; use scope let; use scope nonlocal; // default for backwards compatibility which would obviate the need to add all these |var { ... }| and |let { ... }| statements in new code. For example, the following would be equivalent to the above examples: --- use scope var; function list(iterable) { if (iterable is Array) { lst = iterable; } else { list = []; for (x in iterable) { lst.push(x); } } return lst; } function stats(iterable) { lst = list(iterable); function calcSum() { sum = 0; for each (x in lst) { sum += x; } } sum = calcSum(); var mean; function calcMean() { use scope nonlocal; // notice that these pragmas can be local to blocks mean = sum / lst.length; } return [lst.length, sum, mean]; } --- I should also point out that this is not a radical new concept. Both Ruby and Python have had this functionality for a while. Comments? -Yuh-Ruey Chen _______________________________________________ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss