Generalize do-expressions to statements in general?
Isiah Meadows
impinball at gmail.com
Mon Jul 13 22:47:19 UTC 2015
I was reading a recent thread
<https://esdiscuss.org/topic/allow-try-catch-blocks-to-return-a-value> where
do-expressions simplified a common try-catch use case, and I was wondering
if `do` could be simplified to an expression? It would allow for this to be
solved very easily, but also add a lot more flexibility in this proposal,
as well as avoiding some ugly nested braces.
I know it would cause an ambiguity with `do-while` loops, but that could be
resolved with a single token lookahead of "if the next token is the keyword
`while`, then the block body is the body of a do-while loop, else it is the
body of the block statement in a `do` expression".
As for the EBNF, do-expressions could be parsed with a goal symbol of
either `+While` or `-While`, with do-while statements spec-wise effectively
being treated as do-expressions without an init part run repetitively, but
mandated to be statements.
```js
// Do expression
let foo = do {
foo(0)
};
let tried = do try {
foo(0)
} catch (e) {
throw e
};
// Do-while statement
let i = 0;
do {
foo(i)
} while (i++ < 10);
// Combined:
let i = 0;
let foo9 = do do {
foo(i) // can have side effects, foo9 = foo(9)
} while (i++ < 10);
```
Another example of where this could come in handy: simplifying asynchronous
code.
```js
function readConfig() {
fs.readFileAsync('config.json', 'utf8')
.then(JSON.parse)
.then(contents => do if (contents.unexpectedProperty) {
throw new Error('Bad property') // rejects the promise
} else {
doSomething(contents)
})
.catch(err => process.domain.emit('err', error))
}
// With only block statement
function readConfig() {
fs.readFileAsync('config.json', 'utf8')
.then(JSON.parse)
.then(contents => do {
if (contents.unexpectedProperty) {
throw new Error('Bad property') // rejects the promise
} else {
doSomething(contents)
}
})
.catch(err => process.domain.emit('err', error))
}
// Without do-expressions
function readConfig() {
fs.readFileAsync('config.json', 'utf8')
.then(JSON.parse)
.then(contents => {
if (contents.unexpectedProperty) {
throw new Error('Bad property') // rejects the promise
} else {
doSomething(contents)
}
})
.catch(err => process.domain.emit('err', error))
}
```
As you can see, the more general version does simplify things a little.
Also, if-statements look better than long ternaries IMHO, and are less
repetitive than their counterpart, repeated assignment (us lazy typists...):
```js
let foo = do if (someCondition) {
value
} else if (someOtherCondition) {
value + 1
} else if (someEdgeCase) {
addressEdgeCase(value)
} else {
value
}
```
--
Isiah Meadows
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150713/201b7b12/attachment.html>
More information about the es-discuss
mailing list