Alan Plum (2018-02-08T14:50:25.000Z)
Hi everyone,

I'm hoping this is the right medium to ask this but I would like to
propose a language feature called try/catch/else.
Conditional try/catch seems to be all the rage right now but in many
cases the problem it really wants to solve seems to be code like the
following:
try {
  const suggestions = await fetchSuggestions();
  showSuggestions(suggestions);
} catch (e) {
  alert('Failed to load suggestions');
  // Oops, we also swallow errors from showSuggestions
}
// now do something else

Having a more fine-grained catch wouldn't necessarily help here because
both functions might throw the same kind of error but what we're really
interested in is discerning the *source* of the error. So instead some
people resort to something like this:
let suggestions;
try {
  suggestions = await fetchSuggestions();
} catch (e) {
  alert('Failed to load suggestions');
  return;
}
showSuggestions(suggestions);
// now do something else - unless we failed to load

Note how we're forced to add a return to explicitly abort the control
flow. Unlike the change from const to let this isn't something an IDE
would point out while refactoring, so this actually introduces potential
for bugs. If we don't actually want to bail out completely this often
leads to noisy status booleans (e.g. didNotThrow) or error-prone checks
(e.g. !suggestions is a bug if the async function really didn't return
anything).
I'm not sure about other languages but Python has a solution for this by
adding an else clause:
let suggestions;
try {
  suggestions = await fetchSuggestions();
} catch (e) {
  alert('Failed to load suggestions');
} else {
  showSuggestions(suggestions);
}
// now do something else

The semantics are pretty straightforward: if the try block did not
throw, the else block is executed next (before the finally block if
any). If the try block does throw, the else block is ignored (like a
conditional catch that doesn't match).
I realise there is some ambiguity in using the else keyword for this
(though I can't think of a meaningful opposite of "catch" either). There
is also some overlap with conditional try/catch but I think this
language feature is useful even if conditional try/catch exists.

Cheers,

Alan Plum
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180208/185565f5/attachment-0001.html>
me at pluma.io (2018-02-08T14:52:42.309Z)
I'm hoping this is the right medium to ask this but I would like to
propose a language feature called try/catch/else.

Conditional try/catch seems to be all the rage right now but in many
cases the problem it really wants to solve seems to be code like the
following:

```
try {
  const suggestions = await fetchSuggestions();
  showSuggestions(suggestions);
} catch (e) {
  alert('Failed to load suggestions');
  // Oops, we also swallow errors from showSuggestions
}
// now do something else
```

Having a more fine-grained catch wouldn't necessarily help here because
both functions might throw the same kind of error but what we're really
interested in is discerning the *source* of the error. So instead some
people resort to something like this:

```
let suggestions;
try {
  suggestions = await fetchSuggestions();
} catch (e) {
  alert('Failed to load suggestions');
  return;
}
showSuggestions(suggestions);
// now do something else - unless we failed to load
```

Note how we're forced to add a return to explicitly abort the control
flow. Unlike the change from const to let this isn't something an IDE
would point out while refactoring, so this actually introduces potential
for bugs. If we don't actually want to bail out completely this often
leads to noisy status booleans (e.g. didNotThrow) or error-prone checks
(e.g. !suggestions is a bug if the async function really didn't return
anything).

I'm not sure about other languages but Python has a solution for this by
adding an else clause:

```
let suggestions;
try {
  suggestions = await fetchSuggestions();
} catch (e) {
  alert('Failed to load suggestions');
} else {
  showSuggestions(suggestions);
}
// now do something else
```

The semantics are pretty straightforward: if the try block did not
throw, the else block is executed next (before the finally block if
any). If the try block does throw, the else block is ignored (like a
conditional catch that doesn't match).

I realise there is some ambiguity in using the else keyword for this
(though I can't think of a meaningful opposite of "catch" either). There
is also some overlap with conditional try/catch but I think this
language feature is useful even if conditional try/catch exists.