digitalmars.D - TryElseExpression DIP
- pineapple (44/44) Sep 05 2016 I was writing some code and realized D doesn't have an equivalent
- ag0aep6g (6/31) Sep 05 2016 Can you point out how this is different from (and better than)
- pineapple (15/29) Sep 05 2016 In this case, the catch block will catch both errors from
- Jacob Carlborg (4/6) Sep 05 2016 Then move it to after the "finally" block.
- arturg (10/46) Sep 05 2016 hm, isn't this similar/same as the python version?
I was writing some code and realized D doesn't have an equivalent to Python's `else` for error handling, and I think we should change that https://github.com/dlang/DIPs/pull/43/files In Python, the try/catch/finally syntax is augmented with an additional clause, termed else. It is a fantastically useful addition to the conventional syntax. It works like this: try: do_something() except Exception as e: raised else: finally: Imitating this functionality in D, try{ do_a_thing(); }catch(Exception exception){ handle_error(); }else{ depends_on_success_of_thing(); }finally{ do_this_always(); } Would be equivalent to bool success = false; try{ do_a_thing(); success = true; }catch(Exception exception){ handle_error(); }finally{ try{ if(success){ depends_on_success_of_thing(); } }finally{ do_this_always(); } }
Sep 05 2016
On 09/05/2016 08:07 PM, pineapple wrote:try{ do_a_thing(); }catch(Exception exception){ handle_error(); }else{ depends_on_success_of_thing(); }finally{ do_this_always(); } Would be equivalent to bool success = false; try{ do_a_thing(); success = true; }catch(Exception exception){ handle_error(); }finally{ try{ if(success){ depends_on_success_of_thing(); } }finally{ do_this_always(); } }Can you point out how this is different from (and better than) try { do_a_thing(); depends_on_success_of_thing(); } catch (...) { ... } finally { ... } ?
Sep 05 2016
On Monday, 5 September 2016 at 18:27:44 UTC, ag0aep6g wrote:Can you point out how this is different from (and better than) try { do_a_thing(); depends_on_success_of_thing(); } catch (...) { ... } finally { ... } ?On Monday, 5 September 2016 at 18:27:52 UTC, arturg wrote:hm, isn't this similar/same as the python version? try{ doSomething(); scope(success) "if no Exception thrown".writeln; } catch(Exception e) { ... }In this case, the catch block will catch both errors from do_a_thing and depends_on_success_of_thing. The places where this sort of pattern is most useful are where you don't want to handle errors in depends_on_success_of_thing at all, because to have thrown an error is very unexpected behavior. Granted scenarios like that are uncommon, but the most important reason for using the separate `else` scope is to help reduce programmer error because they forgot that the error handling in the catch block will break something when it was entered because depends_on_success_of_thing failed. There's also the matter of readability and cleanliness. It is (in my opinion, at least) an intuitive and concise way to handle a not-uncommon case.
Sep 05 2016
On 2016-09-05 20:57, pineapple wrote:In this case, the catch block will catch both errors from do_a_thing and depends_on_success_of_thing.Then move it to after the "finally" block. -- /Jacob Carlborg
Sep 05 2016
On Monday, 5 September 2016 at 19:12:02 UTC, Jacob Carlborg wrote:On 2016-09-05 20:57, pineapple wrote:It would actually have to be inside the "finally" block to reproduce the exact behavior. I included an analog in the original post - I'm not saying that this behavior can't be achieved now, but that this is a concise and more readable pattern which, when utilized, makes it more difficult to accidentally write error-prone code. Which is easier to read and to write? Which is more maintainable? Which is less prone to programmer errors? This? bool success = false; try{ do_a_thing(); success = true; }catch(Exception exception){ handle_error(); }finally{ try{ if(success){ depends_on_success_of_thing(); } }finally{ do_this_always(); } } Or this? try{ do_a_thing(); }catch(Exception exception){ handle_error(); }else{ depends_on_success_of_thing(); }finally{ do_this_always(); } This? try{ do_a_thing(); }else{ depends_on_success_of_thing(); } Or this? bool success = false; try{ do_a_thing(); success = true; }finally{ if(success){ depends_on_success_of_thing(); } }In this case, the catch block will catch both errors from do_a_thing and depends_on_success_of_thing.Then move it to after the "finally" block.
Sep 05 2016
On Monday, 5 September 2016 at 20:04:43 UTC, pineapple wrote:On Monday, 5 September 2016 at 19:12:02 UTC, Jacob Carlborg wrote: [...]There's probably also a FP approach: function TryElse( alias TryStatements, alias ElseStatements)(){} function TryCatchElseFinally( alias TryStatements, alias ElseStatements, alias CatchStatements, alias ElseStatements, E : Exception = Exception)(){} etc. You pass delegate literals: °°°°°°°°°°°°°°°°°°°°° void TryElse(alias TryStatements, alias ElseStatements)() { bool doElses = true; try TryStatements(); catch(Throwable){} ElseStatements(); } void main() { int i; import std.conv: to; TryElse!( {i = to!int("0.42");}, {i = -1;} ); } °°°°°°°°°°°°°°°°°°°°° With optional sugar to name each statements group: °°°°°°°°°°°°°°°°°°°°° template Statements(alias T) { alias Statements = T; } alias Try = Statements; alias Else = Statements; void main() { TryElse!( Try!({}), Else!({}) ); } °°°°°°°°°°°°°°°°°°°°°On 2016-09-05 20:57, pineapple wrote:Which is easier to read and to write? Which is more maintainable? Which is less prone to programmer errors? This? [...] This? try{ do_a_thing(); }else{ depends_on_success_of_thing(); } Or this? bool success = false; try{ do_a_thing(); success = true; }finally{ if(success){ depends_on_success_of_thing(); } }
Sep 05 2016
On Monday, 5 September 2016 at 18:07:52 UTC, pineapple wrote:It works like this: try: do_something() except Exception as e: raised else: finally: Imitating this functionality in D, try{ do_a_thing(); }catch(Exception exception){ handle_error(); }else{ depends_on_success_of_thing(); }finally{ do_this_always(); } Would be equivalent to bool success = false; try{ do_a_thing(); success = true; }catch(Exception exception){ handle_error(); }finally{ try{ if(success){ depends_on_success_of_thing(); } }finally{ do_this_always(); } }hm, isn't this similar/same as the python version? try{ doSomething(); scope(success) "if no Exception thrown".writeln; } catch(Exception e) { ... }
Sep 05 2016