Since ES is not an expression language, it's useful to divide the question into
TC for expressions
expr equiv (function(){return expr;})()
ES violations: this, arguments.
'this' breakage can possibly be addressed with '.bind(this)' as in
my previous message.
expr equiv (function(){return expr;}).call(this)
TC for blocks
{stats} equiv (function(){stats})();
Same issues re this, arguments
Additional ES violations: return, break, continue, var hoisting
Note: The above litany of problems are not fixable in ES. But we
should try to avoid digging this hole any deeper.
Any procedural language will have issues with TC then. The only longterm
solution to this that I can think of is to add Ruby-like code blocks to
the language, which inherit this, arguments, var scope, and
return/break/continue continuations.
Not ever having dealt with implementing continuations, I have no idea
how simple it would be to add code block semantics to the language.
There are two styles to code blocks that I know of, which are not
mutually exclusive:
adding a new type of function
denoting that a parameter to a function is a block, and treating any
function passed in as that parameter to be a block
In either style, the function artifacts (this, arguments, etc.) would be
determined lexically.
The first style would require some new syntax to define blocks.
Redefining |this| via function.call and function.apply should also be
disallowed. We have several options to choose from. Some examples:
Ruby-like:
do(...) { ... }
do { ... }
Usage of Java keywords:
function(...) inherits { ... }
Some obscure yet convenient syntax:
#(...) { ... }
The second style would require some sort of block annotation to a
parameter, e.g.
One advantage of the second style is that we can add new types of
control abstractions relatively seamlessly with some more Ruby-like
sugar. If the last parameter to a function is annotated to be a block,
then the following:
function control(..., block f) { ... }
control(...) statement
would pass in a 0-parameter code block composed of |statement| (which
could be a {...} block) to the function |control| as the parameter f.
Example:
function read(openArg, block f) {
try {
this.open(openArg);
f();
} finally {
this.close();
}
}
FileInputStream.prototype.read = read;
function findInFiles(files, x) {
for each (let file in files) {
input = new FileInputStream();
input.read(file) {
let lineNum = 0;
for (let line in input.readLines()) {
if (line == x)
return [file, lineNum];
lineNum++;
}
}
}
}
Hope that all made sense.
-Yuh-Ruey Chen
Mark S. Miller wrote:
> Since ES is not an expression language, it's useful to divide the question into
>
> * TC for expressions
> expr equiv (function(){return expr;})()
> ES violations: this, arguments.
> 'this' breakage can possibly be addressed with '.bind(this)' as in
> my previous message.
> expr equiv (function(){return expr;}).call(this)
>
> * TC for blocks
> {stats} equiv (function(){stats})();
> Same issues re this, arguments
> Additional ES violations: return, break, continue, var hoisting
>
> Note: The above litany of problems are not fixable in ES. But we
> should try to avoid digging this hole any deeper.
Any procedural language will have issues with TC then. The only longterm
solution to this that I can think of is to add Ruby-like code blocks to
the language, which inherit this, arguments, var scope, and
return/break/continue continuations.
Not ever having dealt with implementing continuations, I have no idea
how simple it would be to add code block semantics to the language.
There are two styles to code blocks that I know of, which are not
mutually exclusive:
1) adding a new type of function
2) denoting that a parameter to a function is a block, and treating any
function passed in as that parameter to be a block
In either style, the function artifacts (this, arguments, etc.) would be
determined lexically.
The first style would require some new syntax to define blocks.
Redefining |this| via function.call and function.apply should also be
disallowed. We have several options to choose from. Some examples:
Ruby-like:
do(...) { ... }
do { ... }
Usage of Java keywords:
function(...) inherits { ... }
Some obscure yet convenient syntax:
#(...) { ... }
The second style would require some sort of block annotation to a
parameter, e.g.
function(x: block} { ... }
function(block x) { ... }
function(&x) { ... }
One advantage of the second style is that we can add new types of
control abstractions relatively seamlessly with some more Ruby-like
sugar. If the last parameter to a function is annotated to be a block,
then the following:
function control(..., block f) { ... }
control(...) statement
would pass in a 0-parameter code block composed of |statement| (which
could be a {...} block) to the function |control| as the parameter f.
Example:
function read(openArg, block f) {
try {
this.open(openArg);
f();
} finally {
this.close();
}
}
FileInputStream.prototype.read = read;
function findInFiles(files, x) {
for each (let file in files) {
input = new FileInputStream();
input.read(file) {
let lineNum = 0;
for (let line in input.readLines()) {
if (line == x)
return [file, lineNum];
lineNum++;
}
}
}
}
Hope that all made sense.
-Yuh-Ruey Chen
Mark S. Miller wrote:
Any procedural language will have issues with TC then. The only longterm solution to this that I can think of is to add Ruby-like code blocks to the language, which inherit this, arguments, var scope, and return/break/continue continuations.
Not ever having dealt with implementing continuations, I have no idea how simple it would be to add code block semantics to the language.
There are two styles to code blocks that I know of, which are not mutually exclusive:
In either style, the function artifacts (this, arguments, etc.) would be determined lexically.
The first style would require some new syntax to define blocks. Redefining |this| via function.call and function.apply should also be disallowed. We have several options to choose from. Some examples:
Ruby-like: do(...) { ... } do { ... }
Usage of Java keywords: function(...) inherits { ... }
Some obscure yet convenient syntax: #(...) { ... }
The second style would require some sort of block annotation to a parameter, e.g.
One advantage of the second style is that we can add new types of control abstractions relatively seamlessly with some more Ruby-like sugar. If the last parameter to a function is annotated to be a block, then the following:
would pass in a 0-parameter code block composed of |statement| (which could be a {...} block) to the function |control| as the parameter f. Example:
Hope that all made sense.
-Yuh-Ruey Chen