Re: try/catch/else
Oops, you're right. I agree that `else` might not be the best keyword for this all things considering. On Tue, Feb 13, 2018, at 1:48 PM, T.J. Crowder wrote: > On Tue, Feb 13, 2018 at 12:37 PM, Alan Plumwrote: > > Not quite. > > You appear to have missed my message three minutes later, after I'd > realized that: > https://esdiscuss.org/topic/try-catch-else#content-16 > > -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
On Tue, Feb 13, 2018 at 12:37 PM, Alan Plumwrote: > Not quite. You appear to have missed my message three minutes later, after I'd realized that: https://esdiscuss.org/topic/try-catch-else#content-16 -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
Not quite. If the `else` (or `nocatch`, whatever) block throws, it would bypass the `catch` block but still hit the `finally` block the same way an exception in the `catch` block would: * if `a` doesn't throw: a, b, d * if `a` throws: a, c, d * if `b` throws: a, b, d * if `a` and `c` throw: a, c, d This is analogous to this promise equivalent: ``` console.log("a"); a() .then(() => { console.log("b"); return b(); }, () => { console.log("c"); return c(); }) .finally(() => { console.log("d"); }) ``` (note the use of both arguments to `then`) Your reading wouldn't really provide anything that can't be done by simply moving the else block's content into the try block. -- Alan Plum m...@pluma.io On Tue, Feb 13, 2018, at 12:54 PM, T.J. Crowder wrote: > On Tue, Feb 13, 2018 at 11:30 AM, Isiah Meadows >wrote:> > > > If you did `else` before `catch`/`finally`, that'd solve your > > problem. ;-)> > > > The catch with `finally` (no pun intended) is this: does/should it > > execute *before* or *after* else? > > Logically it makes sense `finally` would be after, so putting the > `else` after `try` and before `catch`/`finally` makes sense for that > reason as well:> > ```js > try { > console.log('a'); > a(); > } else { > console.log('b'); > b(); > } catch (e) { > console.log('c'); > c(); > } finally { > console.log('d'); > d(); > } > ``` > > Then > > * If `a` doesn't throw: a, b, d. > * If `a` throws: a, c, d. > * If `b` throws: a, b, c, d > * If `a` and `c` both throw: a, c, d > * If `b` and `c` both throw: a, b, c, d > > `else` doesn't make sense in English terms anymore, though. `then` > would though, and on first blush would be consistent with what the > promise version of this would look like:> > ```js > console.log("a"); > a() > .then(() => { > console.log("b"); > return b(); > }) > .catch(() => { > console.log("c"); > return c(); > }) > .finally(() => { > console.log("d"); > }) > ``` > > -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
On Tue, Feb 13, 2018 at 11:54 AM, T.J. Crowderwrote: > > Then > > * If `a` doesn't throw: a, b, d. > * If `a` throws: a, c, d. > * If `b` throws: a, b, c, d > * If `a` and `c` both throw: a, c, d > * If `b` and `c` both throw: a, b, c, d Gah, I forgot that you don't want the `else` block subject to the `catch`. So ignore that, and it no longer resembles the promise version. Don't like `else` in front of `catch` if exceptions from the code in the `else` isn't caught. -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
On Tue, Feb 13, 2018 at 11:30 AM, Isiah Meadowswrote: > > If you did `else` before `catch`/`finally`, that'd solve your problem. ;-) > > The catch with `finally` (no pun intended) is this: does/should it > execute *before* or *after* else? Logically it makes sense `finally` would be after, so putting the `else` after `try` and before `catch`/`finally` makes sense for that reason as well: ```js try { console.log('a'); a(); } else { console.log('b'); b(); } catch (e) { console.log('c'); c(); } finally { console.log('d'); d(); } ``` Then * If `a` doesn't throw: a, b, d. * If `a` throws: a, c, d. * If `b` throws: a, b, c, d * If `a` and `c` both throw: a, c, d * If `b` and `c` both throw: a, b, c, d `else` doesn't make sense in English terms anymore, though. `then` would though, and on first blush would be consistent with what the promise version of this would look like: ```js console.log("a"); a() .then(() => { console.log("b"); return b(); }) .catch(() => { console.log("c"); return c(); }) .finally(() => { console.log("d"); }) ``` -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
Going with python's semantics, finally should execute after else because else behaves analogous to catch. It's basically a "nocatch". On Tue, Feb 13, 2018, at 12:30 PM, Isiah Meadows wrote: > If you did `else` before `catch`/`finally`, that'd solve your problem. ;-) > > The catch with `finally` (no pun intended) is this: does/should it > execute *before* or *after* else? > - > > Isiah Meadows > m...@isiahmeadows.com > > Looking for web consulting? Or a new website? > Send me an email and we can get started. > www.isiahmeadows.com > > > On Tue, Feb 13, 2018 at 4:48 AM, Alan Plumwrote: > > Yikes, thanks for pointing that out. I guess this could be resolved by > > having a lower precedence for `catch/else` than `if/else` or by enforcing > > the sequence `try/else/catch` (as `try` without `catch` or `finally` is a > > syntax error). > > > > > > On Tue, Feb 13, 2018, at 2:06 AM, Waldemar Horwat wrote: > >> On 02/08/2018 06:50, Alan Plum wrote: > >> > 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). > >> > >> Indeed. You can't use 'else' without breaking existing behavior. For > >> example: > >> > >> if (foo) try {...} catch (e) {...} else {...} > >> > >> Waldemar > > ___ > > es-discuss mailing list > > es-discuss@mozilla.org > > https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
If you did `else` before `catch`/`finally`, that'd solve your problem. ;-) The catch with `finally` (no pun intended) is this: does/should it execute *before* or *after* else? - Isiah Meadows m...@isiahmeadows.com Looking for web consulting? Or a new website? Send me an email and we can get started. www.isiahmeadows.com On Tue, Feb 13, 2018 at 4:48 AM, Alan Plumwrote: > Yikes, thanks for pointing that out. I guess this could be resolved by having > a lower precedence for `catch/else` than `if/else` or by enforcing the > sequence `try/else/catch` (as `try` without `catch` or `finally` is a syntax > error). > > > On Tue, Feb 13, 2018, at 2:06 AM, Waldemar Horwat wrote: >> On 02/08/2018 06:50, Alan Plum wrote: >> > 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). >> >> Indeed. You can't use 'else' without breaking existing behavior. For >> example: >> >> if (foo) try {...} catch (e) {...} else {...} >> >> Waldemar > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
Yikes, thanks for pointing that out. I guess this could be resolved by having a lower precedence for `catch/else` than `if/else` or by enforcing the sequence `try/else/catch` (as `try` without `catch` or `finally` is a syntax error). On Tue, Feb 13, 2018, at 2:06 AM, Waldemar Horwat wrote: > On 02/08/2018 06:50, Alan Plum wrote: > > 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). > > Indeed. You can't use 'else' without breaking existing behavior. For > example: > > if (foo) try {...} catch (e) {...} else {...} > > Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
On 02/08/2018 06:50, Alan Plum wrote: 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). Indeed. You can't use 'else' without breaking existing behavior. For example: if (foo) try {...} catch (e) {...} else {...} Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
The idea isn't to make the second call's exceptions silent, it's not to catch them (i.e. let them propagate).On 9 Feb 2018 2:46 p.m., Augusto Mourawrote:I see this operator quite confusing, in my opinion it's a best practice treat the functions (and errors) separately. If you want to ignore the second error you can even create a `silent` helper.```jsconst treatedShowSuggestions = (suggs) => { try { showSuggestions(suggs); } catch (e) { // treat error};try { const suggestions = await fetchSuggestions(); treatedShowSuggestions(suggestions);} catch (e) { alert('Failed to load suggestions');}```or```jsconst silent = (fn) => { try { fn(); } catch (e) {}};try { const suggestions = await fetchSuggestions(); silent(() => showSuggestions(suggestions));} catch (e) { alert('Failed to load suggestions');}```This isn't even a workaround, it's just the right approach for what you want. If you wanna to evict the separated functions you can just inline the try/catch in the main function.-- Augusto Moura ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
I see this operator quite confusing, in my opinion it's a best practice treat the functions (and errors) separately. If you want to ignore the second error you can even create a `silent` helper. ```js const treatedShowSuggestions = (suggs) => { try { showSuggestions(suggs); } catch (e) { // treat error }; try { const suggestions = await fetchSuggestions(); treatedShowSuggestions(suggestions); } catch (e) { alert('Failed to load suggestions'); } ``` or ```js const silent = (fn) => { try { fn(); } catch (e) {} }; try { const suggestions = await fetchSuggestions(); silent(() => showSuggestions(suggestions)); } catch (e) { alert('Failed to load suggestions'); } ``` This isn't even a workaround, it's just the right approach for what you want. If you wanna to evict the separated functions you can just inline the try/catch in the main function. -- Augusto Moura ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
> Le 9 févr. 2018 à 00:19, Peter van der Zeea écrit : > >>> On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache >>> wrote: What about the following pattern (labelled block + break)? ```js processSuggestions: { let suggestions; try { suggestions = await fetchSuggestions(); } catch (e) { alert('Failed to load suggestions'); break processSuggestions; } showSuggestions(suggestions); } ``` > > I don't mean to hijack this tread. I'm mostly curious why you opt or > even suggest for that over putting it in a function and an early > return? Like; > > ``` > function processSuggestions() { > let suggestions > try { >suggestions = await fetchSuggestions(); > } catch (e) { >return alert('Failed to load suggestions'); > } > showSuggestions(suggestions); > } > ``` > > This is almost identical, especially the way the example was written. > I understand the differences, I don't think they're a problem for by > far most cases where you'd want this. A function is strictly more complex than a block because you have to define it first, then to invoke it. As a consequence, it is more code to write and read. Unless you have a good reason for it (which is not suggested by the original problem), why would you prefer the more complex way? —Claude ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
I think the best argument for having try/catch/else is that it makes it trivial to translate promises into async/await. Consider this: ``` let result = a() .then(b, c) .catch(d); ``` If we want to translate this 1:1 to try/catch/else in an async function we'll end up with something like this: ``` try { let x, y; try { x = await a(); } catch (e) { y = await c(e); } else { y = await b(x); } return y; } catch (e) { return await d(e); } ``` Doing this without `else` would require one of the workarounds suggested upthread. On Thu, Feb 8, 2018, at 7:13 PM, Claude Pache wrote: > What about the following pattern (labelled block + break)? > > ```js > processSuggestions: { > let suggestions; > try { > suggestions = await fetchSuggestions(); > } catch (e) { > alert('Failed to load suggestions'); > break processSuggestions; > } > showSuggestions(suggestions); > } > ``` > > —Claude ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
>> On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache>> wrote: >>> >>> What about the following pattern (labelled block + break)? >>> >>> ```js >>> processSuggestions: { >>> let suggestions; >>> try { >>> suggestions = await fetchSuggestions(); >>> } catch (e) { >>> alert('Failed to load suggestions'); >>> break processSuggestions; >>> } >>> showSuggestions(suggestions); >>> } >>> ``` I don't mean to hijack this tread. I'm mostly curious why you opt or even suggest for that over putting it in a function and an early return? Like; ``` function processSuggestions() { let suggestions try { suggestions = await fetchSuggestions(); } catch (e) { return alert('Failed to load suggestions'); } showSuggestions(suggestions); } ``` This is almost identical, especially the way the example was written. I understand the differences, I don't think they're a problem for by far most cases where you'd want this. That said I wouldn't mind seeing try/catch/else/finally because the pattern(s) above still leads to awkward code in the real world. One could bikeshed on how "else" implies the attempt ("try") to have failed rather than succeeded. On the other hand making it try/then/catch/finally is also going to be confusing so whatever :) - peter ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
I honestly wish engines (read: V8) didn't jave so much issue optimizing that. But yes, it's a very useful pattern. On Thu, Feb 8, 2018, 14:35 Mark Millerwrote: > Hi Claude, that's nice. Whenever I faced this issue I always turned to the > boolean flag variable. But this is strictly better. I expect to use it from > now on. Thanks! > > > On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache > wrote: > >> What about the following pattern (labelled block + break)? >> >> ```js >> processSuggestions: { >> let suggestions; >> try { >> suggestions = await fetchSuggestions(); >> } catch (e) { >> alert('Failed to load suggestions'); >> break processSuggestions; >> } >> showSuggestions(suggestions); >> } >> ``` >> >> —Claude >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > > -- > Cheers, > --MarkM > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
Hi Claude, that's nice. Whenever I faced this issue I always turned to the boolean flag variable. But this is strictly better. I expect to use it from now on. Thanks! On Thu, Feb 8, 2018 at 10:13 AM, Claude Pachewrote: > What about the following pattern (labelled block + break)? > > ```js > processSuggestions: { > let suggestions; > try { > suggestions = await fetchSuggestions(); > } catch (e) { > alert('Failed to load suggestions'); > break processSuggestions; > } > showSuggestions(suggestions); > } > ``` > > —Claude > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
What about the following pattern (labelled block + break)? ```js processSuggestions: { let suggestions; try { suggestions = await fetchSuggestions(); } catch (e) { alert('Failed to load suggestions'); break processSuggestions; } showSuggestions(suggestions); } ``` —Claude ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
Sounds good in principle but I think the name is misleading. Actually try/catch/else is the synchronous equivalent of tryFn().then(elseFn, catchFn) but then has other implications (it returns a new promise and the then method actually takes two functions). Calling it then would imply it's equivalent to tryFn().then(thenFn).catch(catchFn) which is actually just the same as the first example, not the try/catch/else. I also think having the else after the catch makes the intention clearer (just like finally comes after catch and else). On Thu, Feb 8, 2018, at 4:20 PM, Michael Luder-Rosefield wrote: > Well, since promise.then(/**blah**/).catch(/**blah**/) is already a > thing, why not stick with that?> > try { > // blah > } then(val) { > // blah > } catch { > // blah > } finally { > // blah > } > > I added `val` to the then since we might want to pass something from > `try` to it, just as promises do. Best way to do that might be for > `try` to act as an expression block and implicitly return the last > thing in it.> > On Thu, 8 Feb 2018 at 14:50 Alan Plumwrote: >> __ >> 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 >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: try/catch/else
Well, since promise.then(/**blah**/).catch(/**blah**/) is already a thing, why not stick with that? try { // blah } then(val) { // blah } catch { // blah } finally { // blah } I added `val` to the then since we might want to pass something from `try` to it, just as promises do. Best way to do that might be for `try` to act as an expression block and implicitly return the last thing in it. On Thu, 8 Feb 2018 at 14:50 Alan Plumwrote: > 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 > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss