digitalmars.D - DIP 1002 (TryElseExpression) added to the queue
- Dicebot (17/17) Sep 27 2016 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md
- Jonathan M Davis via Digitalmars-d (6/23) Sep 27 2016 And why not just put the code that would go in the else at the end of th...
- Idan Arye (18/48) Sep 27 2016 Exceptions thrown in the `else` clause are not caught in the
- pineapple (3/5) Sep 27 2016 The catch and finally clauses do currently continue the scope,
- pineapple (13/19) Sep 27 2016 This is a commonly-used tool that makes code more readable and
- John Colvin (25/42) Sep 27 2016 What's annoying is that we already have finally, which can be
- Steven Schveighoffer (16/40) Sep 27 2016 Hm... I always thought scope(exit) is lowered to:
- Walter Bright (2/11) Sep 27 2016 try/catch/finally is the building block, other constructs are lowered to...
- Nick Treleaven (13/29) Sep 30 2016 C) Use collectException:
- Walter Bright (26/42) Sep 27 2016 The DIP says that a state variable is currently necessary, but that is i...
- John Colvin (5/47) Sep 27 2016 That's not the same. Exceptions thrown in the success block can
- Walter Bright (2/5) Sep 28 2016 Yeah, you're right. I should have tested it. A flag will fix it :-)
- ikod (5/22) Sep 28 2016 Thanks!
- pineapple (9/13) Sep 28 2016 While I appreciate being able to use for/else and while/else in
- Andrei Alexandrescu (71/87) Sep 28 2016 Thanks for the submission. I made on pass through the document and it
- Andrea Fontana (7/25) Sep 28 2016 Why not an optional syntax like:
- pineapple (20/51) Sep 28 2016 These were not documented as a requirement anywhere that I saw.
- Dicebot (29/59) Sep 28 2016 protected-headers="v1"
- Andrei Alexandrescu (4/6) Sep 28 2016 It's not a sign of rejection at all! I'm not even discussing the
- Idan Arye (23/43) Sep 28 2016 I'm the one who suggested that, and I believe there is a very
- Andrei Alexandrescu (20/49) Sep 28 2016 Yah, we're also learning the ropes. Bear with us - this is one of the
- Dicebot (14/15) Sep 28 2016 protected-headers="v1"
- John Colvin (12/25) Sep 28 2016 Yeah... that's a pain.
- pineapple (2/2) Sep 28 2016 I submitted a PR addressing some of the mentioned criticisms:
- Andrei Alexandrescu (95/97) Sep 28 2016 Thanks. The Phobos examples compared:
- Andrei Alexandrescu (10/16) Sep 28 2016 Sorry, this is not semantically equivalent. Replace with:
- John Colvin (9/27) Sep 29 2016 Aren't those the same, as assert won't ever throw a
- Andrei Alexandrescu (2/30) Sep 29 2016 Correct, thanks. -- Andrei
- Steven Schveighoffer (16/42) Sep 28 2016 No. Just no ;)
- Steven Schveighoffer (3/6) Sep 28 2016 Didn't finish this sentence. "very obscure"
- pineapple (25/32) Sep 28 2016 This is not and was not intended to be a glorious, incredible
- pineapple (5/14) Sep 28 2016 Or, more concisely:
- Andrei Alexandrescu (10/23) Sep 29 2016 A DIP should stay as far away from this kind of argument as possible.
- Walter Bright (4/7) Sep 29 2016 More generally, a problem with existing feature X is not a justification...
- Timon Gehr (6/15) Sep 29 2016 I posit you often just misunderstand what the argument is: It's more
- Steven Schveighoffer (20/45) Sep 28 2016 The main question to answer is how big is this "Everywhere". I've never
- Idan Arye (22/27) Sep 28 2016 Consider this:
- Walter Bright (14/22) Sep 28 2016 I agree with Steven. Having the 'else' continue on with a scope that is ...
- Jack Stouffer (10/19) Sep 29 2016 Seconded
- Marc =?UTF-8?B?U2Now7x0eg==?= (4/14) Sep 29 2016 And `Foo` could have `@disabled this()`, so you simply _can't_
- Walter Bright (2/4) Sep 29 2016 Foo foo = void;
- Marc =?UTF-8?B?U2Now7x0eg==?= (3/8) Oct 02 2016 That's even worse. At least Foo.init would be deterministic.
- Steven Schveighoffer (16/41) Sep 29 2016 This is what I meant:
- Nick Treleaven (26/35) Sep 29 2016 Assuming for a minute that we want some form of DIP1002, we might
- pineapple (9/14) Sep 29 2016 While I think finally(bool) is a decent approach, the languages
- Steven Schveighoffer (11/23) Sep 29 2016 In fact, finally(bool) can be extended to:
- crimaniak (64/77) Sep 30 2016 My 5 cents, let's play:
- ikod (2/15) Sep 28 2016 Agree, programming should be fun, not struggle.
- Walter Bright (3/20) Sep 28 2016 These are great suggestions and apply generally. They should be added to...
- Jack Stouffer (9/15) Sep 28 2016 I support this addition because, while it's possible to mimic
- Andrei Alexandrescu (12/29) Sep 28 2016 This rough count:
- Jack Stouffer (7/14) Sep 28 2016 This is based on my anecdotal experience. I also posted an
- John Colvin (9/23) Sep 28 2016 Yes, scope can't immitate catch else without a flag. It doesn't
- Andrei Alexandrescu (10/20) Sep 29 2016 Thanks, Jack. Here I'm solely focused on making DIP1002 stronger so I've...
- Jack Stouffer (6/10) Sep 29 2016 Ok, I see where you're coming from, you want DIPs to be arguments
- pineapple (12/46) Sep 29 2016 This is actually 100% of why I think scope sharing between `try`,
- Andrei Alexandrescu (12/20) Sep 29 2016 In order to make this kind of argument work, you need evidence. The
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: ```
Sep 27 2016
On Tuesday, September 27, 2016 09:30:10 Dicebot via Digitalmars-d wrote:https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: ```And why not just put the code that would go in the else at the end of the try block? Just like with this proposed else, the code would only run if the preceding code didn't throw any exceptions. This just seems like an attempt to make D more like python rather than to add anything useful. - Jonathan M Davis
Sep 27 2016
On Tuesday, 27 September 2016 at 09:48:42 UTC, Jonathan M Davis wrote:On Tuesday, September 27, 2016 09:30:10 Dicebot via Digitalmars-d wrote:Exceptions thrown in the `else` clause are not caught in the catch/expect clauses. This gives you finer grained control: try { auto f1 = File("f1.txt"); } catch (ErrnoException) { // f1.txt not found? no biggie... } else { // This won't happen if we can't open f1.txt // If we can't open f2 we don't want to catch the exception: auto f2 = File("f2.txt", "w"); // Do stuff with f1 and f2 } // This will still happen even if we can't open f1.txt BTW, if this feature is ever implemented in D, it's important that the else clause will continue the try clause's scope.https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: was raised else: finally: ```And why not just put the code that would go in the else at the end of the try block? Just like with this proposed else, the code would only run if the preceding code didn't throw any exceptions. This just seems like an attempt to make D more like python rather than to add anything useful. - Jonathan M Davis
Sep 27 2016
On Tuesday, 27 September 2016 at 10:05:20 UTC, Idan Arye wrote:BTW, if this feature is ever implemented in D, it's important that the else clause will continue the try clause's scope.The catch and finally clauses do currently continue the scope, right? (If they don't, they probably should, too.)
Sep 27 2016
On Tuesday, 27 September 2016 at 09:48:42 UTC, Jonathan M Davis wrote:And why not just put the code that would go in the else at the end of the try block? Just like with this proposed else, the code would only run if the preceding code didn't throw any exceptions. This just seems like an attempt to make D more like python rather than to add anything useful. - Jonathan M DavisThis is a commonly-used tool that makes code more readable and cuts down on programmer error. It's far more concise and digestible than the functional equivalent, which is _not_ to put the code at the end of the `try` block, it's to put it in the `finally` block - refer to the DIP's example for how that works. This is the most important difference between using `else` and doing what you described: Exceptions thrown by the code in the `else` block are not caught by the `catch` statements intended to handle errors by the operation in the `try` block, but not to handle errors resulting from attempting to handle a success state.
Sep 27 2016
On Tuesday, 27 September 2016 at 09:30:10 UTC, Dicebot wrote:https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: ```What's annoying is that we already have finally, which can be reproduced with other language features: { /*finally*/ scope (exit) {} try { do_something(); } catch (Exception e) {} } but we don't (yet) have catch else, which is harder to immitate. Options are: A) the else clause is nothrow (in which case it can just go last inside the try) or B) store a flag and have to use immitation finally: { /*finally*/ scope (exit) {} bool exceptionThrown = false; try { doSomething(); } catch (Exception e) { exceptionThrown = true; } /*else*/ if (!exceptionThrown) {} }
Sep 27 2016
On 9/27/16 6:55 AM, John Colvin wrote:What's annoying is that we already have finally, which can be reproduced with other language features: { /*finally*/ scope (exit) {} try { do_something(); } catch (Exception e) {} }Hm... I always thought scope(exit) is lowered to: try { } finally { // scope exit code here } Which one is the building block? ;)but we don't (yet) have catch else, which is harder to immitate. Options are: A) the else clause is nothrow (in which case it can just go last inside the try) or B) store a flag and have to use immitation finally: { /*finally*/ scope (exit) {} bool exceptionThrown = false; try { doSomething(); } catch (Exception e) { exceptionThrown = true; } /*else*/ if (!exceptionThrown) {} }I tried a few things, including scope(success), but it doesn't seem doable without an extra piece of data. Essentially, the else clause allows you to split your try block into catch-protected code, and non-catch-protected code. Seems like a worthwhile addition, if easily implemented. -Steve
Sep 27 2016
On 9/27/2016 6:22 AM, Steven Schveighoffer wrote:Hm... I always thought scope(exit) is lowered to: try { } finally { // scope exit code here } Which one is the building block? ;)try/catch/finally is the building block, other constructs are lowered to that.
Sep 27 2016
On Tuesday, 27 September 2016 at 10:55:47 UTC, John Colvin wrote:but we don't (yet) have catch else, which is harder to immitate. Options are: A) the else clause is nothrow (in which case it can just go last inside the try) or B) store a flag and have to use immitation finally: { /*finally*/ scope (exit) {} bool exceptionThrown = false; try { doSomething(); } catch (Exception e) { exceptionThrown = true; } /*else*/ if (!exceptionThrown) {} }C) Use collectException: import std.exception; auto ex = collectException!MyException(doSomething()); if (ex) handleException(ex); else { // doSomething succeeded ... } collectException could be improved to catch more than one type of exception, returning the common type. Alternatively it could maybe return a tuple of the exception and the 1-based index of which type of exception was thrown.
Sep 30 2016
On 9/27/2016 2:30 AM, Dicebot wrote:https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: else: finally: ```The DIP says that a state variable is currently necessary, but that is incorrect: try { scope (exit) { Runs unconditionally, evaluates last } scope (success) { runs when no error was raised } do_something(); } catch (Exception e) { Runs when an error inheriting from Exception was raised } Implementation: The try/catch/else/finally could be 'lowered' into the above form. These references should be included in the DIP: http://dlang.org/spec/statement.html#ScopeGuardStatement http://dlang.org/exception-safe.html My opinion: Due to the existence of the ScopeGuardStatement, I feel this new syntax is redundant and needs a much better justification.
Sep 27 2016
On Wednesday, 28 September 2016 at 04:23:56 UTC, Walter Bright wrote:On 9/27/2016 2:30 AM, Dicebot wrote:That's not the same. Exceptions thrown in the success block can be caught by the catch. That scope (success) block is equivalent to just putting its contents immediately after do_something().https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: was raised else: finally: ```The DIP says that a state variable is currently necessary, but that is incorrect: try { scope (exit) { Runs unconditionally, evaluates last } scope (success) { runs when no error was raised } do_something(); } catch (Exception e) { Runs when an error inheriting from Exception was raised }
Sep 27 2016
On 9/27/2016 11:50 PM, John Colvin wrote:That's not the same. Exceptions thrown in the success block can be caught by the catch. That scope (success) block is equivalent to just putting its contents immediately after do_something().Yeah, you're right. I should have tested it. A flag will fix it :-)
Sep 28 2016
On Tuesday, 27 September 2016 at 09:30:10 UTC, Dicebot wrote:https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: ```Thanks! There is also useful for/else construct in Python https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops I'd like to see it in D.
Sep 28 2016
On Wednesday, 28 September 2016 at 07:33:48 UTC, ikod wrote:Thanks! There is also useful for/else construct in Python https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops I'd like to see it in D.While I appreciate being able to use for/else and while/else in Python, in D using gotos provides a more flexible (if more archaic) solution. But if we were to borrow else from Python for loops - which isn't a terrible idea since gotos are messy and make code harder to read - I'd suggest augmenting the construct with another block that evaluates only when the loop _wasn't_ broken. Make a DIP!
Sep 28 2016
On 9/27/16 11:30 AM, Dicebot wrote:https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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: else: finally: ```Thanks for the submission. I made on pass through the document and it needs some work. * Please remove colloquialisms. Characterizations such as "fantastically useful" are unlikely to be a convincing motivator and have no place in a DIP. * The motivation section should showcase examples that currently are not possible or are contorted in D, followed by their alternative implementation using the proposed feature. At best, the example would be taken from existing code (e.g. found in dub, phobos, etc). Next best is code that defines a plausible artifact. * The motivation section should also hypothesize on why the feature did it would be useful to show why D does need the feature even though it already has richer exception handing mechanisms by means of "scope". * The "Description" section should be more detailed and less casual. The grammar changes should be shown in a syntax similar to the current grammar definition. * I saw in the forum that the "else" clause is supposed to run in the scope of the "try" statement, but that is not mentioned in the proposal. Even though that is the semantics in Python, that should be explicit in the document. The proposal should be standalone and fully specified without knowing Python or perusing external links. * The fact above (the "else" clause continues the scope of the statement after "try") is surprising, considering that the "catch" and "finally" clauses introduce their own scopes. The irregularity may confuse users. If the "else" clause is defined to introduce its own scope, it seems the advantages of the proposal are diminished. * The "Breaking changes" section should include how the following change in semantics would be addressed. Consider: try if (expression) try { ... } catch (Exception) { ... } else { ... } finally { ... } This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try". * The example by Jack Stouffer should be also shown translated in current and proposed D. * The example with "do_a_thing()" etc. is superfluous because it does not illustrate why one would want to "write code like this". Please focus on examples that are meaningful and easy with the feature, difficult without. * My understanding is the last example (D rendition) can be expressed like this: scope(exit) do_this_always(); bool success; try { do_a_thing(); success = true; } catch(Exception exception) { handle_error(); } finally { if(success) { depends_on_success_of_thing(); } } There are further simplifications if it is known that handle_error() finishes the flow (by either throwing or an early return). Again, motivating examples would at best show that this pattern is frequent enough and awkward enough to justify the language addition. Andrei
Sep 28 2016
On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:scope(exit) do_this_always(); bool success; try { do_a_thing(); success = true; } catch(Exception exception) { handle_error(); } finally { if(success) { depends_on_success_of_thing(); } }Why not an optional syntax like: finally(bool thrown) { } ?
Sep 28 2016
On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:* Please remove colloquialisms. Characterizations such as "fantastically useful" are unlikely to be a convincing motivator and have no place in a DIP. * The "Description" section should be more detailed and less casual. The grammar changes should be shown in a syntax similar to the current grammar definition.These were not documented as a requirement anywhere that I saw. I'd have been happy to comply, if I had known this was the practice. I don't know enough about how D is compiled to speak meaningfully about implementation details. I am clearly not the only one who's convinced this is a useful feature. I welcome you or anyone else who can more effectively express the idea to make their own contributions to the DIP. On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:* I saw in the forum that the "else" clause is supposed to run in the scope of the "try" statement, but that is not mentioned in the proposal. Even though that is the semantics in Python, that should be explicit in the document. The proposal should be standalone and fully specified without knowing Python or perusing external links. * The fact above (the "else" clause continues the scope of the statement after "try") is surprising, considering that the "catch" and "finally" clauses introduce their own scopes. The irregularity may confuse users. If the "else" clause is defined to introduce its own scope, it seems the advantages of the proposal are diminished.It was an idea that was raised, yes. If catch and finally don't continue the scope of try, then neither should else. That said, it might be preferable if they all did continue try's scope. But this would be a distinct and separate change.* The "Breaking changes" section should include how the following change in semantics would be addressed. Consider: try if (expression) try { ... } catch (Exception) { ... } else { ... } finally { ... } This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try".This possibility hadn't occurred to me. Is that really legal? If so, I'd argue the old behavior should be maintained and also that people shouldn't write such ambiguous code.
Sep 28 2016
protected-headers="v1" From: Dicebot <public dicebot.lv> Newsgroups: d,i,g,i,t,a,l,m,a,r,s,.,D Subject: Re: DIP 1002 (TryElseExpression) added to the queue References: <gruemzcqaupwptfcbefs forum.dlang.org> <nsfsip$25bd$1 digitalmars.com> <laknmragteyowpngvnov forum.dlang.org> In-Reply-To: <laknmragteyowpngvnov forum.dlang.org> --xcWsWOhDuBfOOMFtKwXrlwq0F5R9a1Mb5 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 09/28/2016 01:17 PM, pineapple wrote:On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wr=ote:* Please remove colloquialisms. Characterizations such as "fantastically useful" are unlikely to be a convincing motivator and have no place in a DIP. * The "Description" section should be more detailed and less casual. The grammar changes should be shown in a syntax similar to the current=egrammar definition.=20 These were not documented as a requirement anywhere that I saw. I'd hav=been happy to comply, if I had known this was the practice.As the new DIP process is very young, set of requirements is being fleshed out as we go. Basically what happens is that DIP gets into the queue, Andrei and Walter point out what they don't like and I take notice of it to add to the documented requirements. Merged draft DIPs are not set in stone - Andrei's comment is not sign of immediate rejection but a request to make a PR to improve mentioned thing= s.* The "Breaking changes" section should include how the following change in semantics would be addressed. Consider: try if (expression) try { ... } catch (Exception) { ... } else { ... } finally { ... } This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first=Yes. `try` body is a single statement or block and `if/else` is a legal single statement. Same for `if` statement and `try/catch`."try".=20 This possibility hadn't occurred to me. Is that really legal?If so, I'd argue ... that people shouldn't write such ambiguous code.Proposing language change is a serious responsibility and speculations about how developers should or should not write their code have no place there. If something is currently legal, breaking changes sections _must_ provide means to mitigate the damage or proposal should not be accepted no matter how good it is. --xcWsWOhDuBfOOMFtKwXrlwq0F5R9a1Mb5--
Sep 28 2016
On 9/28/16 7:36 AM, Dicebot wrote:Merged draft DIPs are not set in stone - Andrei's comment is not sign of immediate rejection but a request to make a PR to improve mentioned things.It's not a sign of rejection at all! I'm not even discussing the technical merits of the language feature itself. For now I'm looking at ways to make it better. -- Andrei
Sep 28 2016
On Wednesday, 28 September 2016 at 11:17:05 UTC, pineapple wrote:On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:I'm the one who suggested that, and I believe there is a very good reason why `else`'s scope behavior should differ from `catch`'s and `try`'s. `catch` and `finally` should not continue `try`'s scope, because they can run even when `try` did not finish successfully(that's their purpose), which means the variables declared in `try` may or may not be initialized in the `catch` and `finally` blocks. For the same reason it's not useful to have them continue the scope - you can't use the variables declared in them if you don't know whether or not they have been initialized. `else` is different - it is guaranteed to only execute if `try` finished successfully, which means all variables in the `try` block have had their initialization statements executed. Also, it's actually useful to have it continue the scope, because one may want to declare a variable in `try`(so they can `catch` exceptions in it's initialization) but use it in `else`(so the same exceptions in it's usage will bubble up). This has little to do with Python's semantics. Python is an interpreted language so it doesn't bother with scope rules for control statements - either the initialization statement was executed and the variable is initialized, or it wasn't and the variable is not declared. D can not imitate this behavior...* I saw in the forum that the "else" clause is supposed to run in the scope of the "try" statement, but that is not mentioned in the proposal. Even though that is the semantics in Python, that should be explicit in the document. The proposal should be standalone and fully specified without knowing Python or perusing external links. * The fact above (the "else" clause continues the scope of the statement after "try") is surprising, considering that the "catch" and "finally" clauses introduce their own scopes. The irregularity may confuse users. If the "else" clause is defined to introduce its own scope, it seems the advantages of the proposal are diminished.It was an idea that was raised, yes. If catch and finally don't continue the scope of try, then neither should else. That said, it might be preferable if they all did continue try's scope. But this would be a distinct and separate change.
Sep 28 2016
On 9/28/16 7:17 AM, pineapple wrote:These were not documented as a requirement anywhere that I saw. I'd have been happy to comply, if I had known this was the practice.Yah, we're also learning the ropes. Bear with us - this is one of the first DIPs using the new flow.I don't know enough about how D is compiled to speak meaningfully about implementation details.I'll formalize this in DIP guide, but some level of implementation discussion is necessary - the more, the better. It has happened in the past (in various languages) that things that seemed sensible were proposed and partially implemented without a clear handle on implementation issues. It would improve the DIP a lot if you collaborated with somebody fluent with implementation issues.I am clearly not the only one who's convinced this is a useful feature. I welcome you or anyone else who can more effectively express the idea to make their own contributions to the DIP.If catch and finally don't continue the scope of try, then neither should else.Then I'd say the DIP should discuss the relative advantages and disadvantages compared to the incarnations in other languages. My understanding is it is important for the "else" branch to continue work initiated in the "try" branch. How well does the feature fare without this amenity? It's the kind of question the DIP should address.That said, it might be preferable if they all did continue try's scope. But this would be a distinct and separate change.The short answer is that will never happen.For a DIP to be successful, its authors need to be fluent with syntactical matters and be able to enumerate them and how they are supposed to be handled ("else" also works with "static if", "version", and since DIP 1002 itself, other "try" statements). Andrei* The "Breaking changes" section should include how the following change in semantics would be addressed. Consider: try if (expression) try { ... } catch (Exception) { ... } else { ... } finally { ... } This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try".This possibility hadn't occurred to me. Is that really legal? If so, I'd argue the old behavior should be maintained and also that people shouldn't write such ambiguous code.
Sep 28 2016
protected-headers="v1" From: Dicebot <public dicebot.lv> Newsgroups: d,i,g,i,t,a,l,m,a,r,s,.,D Subject: Re: DIP 1002 (TryElseExpression) added to the queue References: <gruemzcqaupwptfcbefs forum.dlang.org> <nsfsip$25bd$1 digitalmars.com> In-Reply-To: <nsfsip$25bd$1 digitalmars.com> --g0ieH94qlsM10fMUs6go06WMNV6LRdwnQ Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 09/28/2016 09:47 AM, Andrei Alexandrescu wrote:...I have added references to both your and Walter comments to DIP1002 review section: https://github.com/dlang/DIPs/pull/44 --g0ieH94qlsM10fMUs6go06WMNV6LRdwnQ--
Sep 28 2016
On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:* The "Breaking changes" section should include how the following change in semantics would be addressed. Consider: try if (expression) try { ... } catch (Exception) { ... } else { ... } finally { ... } This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try".Yeah... that's a pain. How about using different keywords: try { // blah } /*else*/ catch (nothrow) { // on success. }
Sep 28 2016
I submitted a PR addressing some of the mentioned criticisms: https://github.com/dlang/DIPs/pull/46
Sep 28 2016
On 9/28/16 9:10 AM, pineapple wrote:I submitted a PR addressing some of the mentioned criticisms: https://github.com/dlang/DIPs/pull/46Thanks. The Phobos examples compared: (1) // Current unittest { bool ok = true; try { auto r2 = assumeSorted([ 677, 345, 34, 7, 5 ]); debug ok = false; } catch (Throwable) { } assert(ok); } // With try/else unittest { try { auto r2 = assumeSorted([ 677, 345, 34, 7, 5 ]); } catch (Throwable) { } else assert(ok); } // Within existing D unittest { try { auto r2 = assumeSorted([ 677, 345, 34, 7, 5 ]); } catch (Throwable) { return; } assert(0); } (2) // Current bool failed = false; try { auto d = c.get!(int); } catch (Exception e) { //writeln(stderr, e.toString); failed = true; } assert(failed); // :o) // With try/else try { auto d = c.get!(int); } catch (Exception e) { } else { assert(0); // :o) } // Within existing D assertThrown(c.get!(int)); (An argument here may be made that assertThrown is "cheating".) (3) // Current void assertNot(string s) { bool b = false; try { decode(s,DecodeMode.STRICT); } catch (DecodeException e) { b = true; } assert(b,s); } // With try/else void assertNot(string s) { try { decode(s,DecodeMode.STRICT); } catch (DecodeException e) {} else { assert(0, s); } } // With scope void assertNot(string s) { try { scope(success) assert(0, s); decode(s,DecodeMode.STRICT); } catch (DecodeException e) {} } The burden is to make the case that the try/else variant is better than the two others. Andrei
Sep 28 2016
On 9/28/16 7:40 PM, Andrei Alexandrescu wrote:// With scope void assertNot(string s) { try { scope(success) assert(0, s); decode(s,DecodeMode.STRICT); } catch (DecodeException e) {} }Sorry, this is not semantically equivalent. Replace with: // With scope void assertNot(string s) { try { decode(s,DecodeMode.STRICT); } catch (DecodeException e) { return; } assert(0, s); } Andrei
Sep 28 2016
On Wednesday, 28 September 2016 at 23:44:19 UTC, Andrei Alexandrescu wrote:On 9/28/16 7:40 PM, Andrei Alexandrescu wrote:Aren't those the same, as assert won't ever throw a DecodeException? Simplest implementation: try { decode(s,DecodeMode.STRICT); assert(0, s); } catch (DecodeException e) {}// With scope void assertNot(string s) { try { scope(success) assert(0, s); decode(s,DecodeMode.STRICT); } catch (DecodeException e) {} }Sorry, this is not semantically equivalent. Replace with: // With scope void assertNot(string s) { try { decode(s,DecodeMode.STRICT); } catch (DecodeException e) { return; } assert(0, s); } Andrei
Sep 29 2016
On 09/29/2016 03:49 AM, John Colvin wrote:On Wednesday, 28 September 2016 at 23:44:19 UTC, Andrei Alexandrescu wrote:Correct, thanks. -- AndreiOn 9/28/16 7:40 PM, Andrei Alexandrescu wrote:Aren't those the same, as assert won't ever throw a DecodeException? Simplest implementation: try { decode(s,DecodeMode.STRICT); assert(0, s); } catch (DecodeException e) {}// With scope void assertNot(string s) { try { scope(success) assert(0, s); decode(s,DecodeMode.STRICT); } catch (DecodeException e) {} }Sorry, this is not semantically equivalent. Replace with: // With scope void assertNot(string s) { try { decode(s,DecodeMode.STRICT); } catch (DecodeException e) { return; } assert(0, s); } Andrei
Sep 29 2016
On 9/28/16 7:58 AM, John Colvin wrote:On Wednesday, 28 September 2016 at 07:47:32 UTC, Andrei Alexandrescu wrote:No. Just no ;) The more I think about this submission, I feel like the benefits are quite slim. The else clause is really simply a disabling of all the exception handlers at the end of the function. The uses seem very There are some funky English problems too. For example, should it be valid to use "else" without a catch? This reads weird: try { ... } else { ...} I think probably the else should be invalid without a valid catch clause. Otherwise, you could just use scope(success). The boolean to indicate an exception was thrown is cumbersome, but not horrible. Having the compiler manage the boolean may make this cleaner (e.g. finally(bool thrown)), I like it better than the else suggestion. -Steve* The "Breaking changes" section should include how the following change in semantics would be addressed. Consider: try if (expression) try { ... } catch (Exception) { ... } else { ... } finally { ... } This code is currently legal and binds the "else" clause to the "if" and the "finally" to the first "try". The proposed feature will bind the "else" and the "finally" to the second try and then probably fail to compile because there is no "catch" or "finally" matching the first "try".Yeah... that's a pain. How about using different keywords: try { // blah } /*else*/ catch (nothrow) { // on success. }
Sep 28 2016
On 9/28/16 1:56 PM, Steven Schveighoffer wrote:The more I think about this submission, I feel like the benefits are quite slim. The else clause is really simply a disabling of all the exception handlers at the end of the function. The uses seem veryDidn't finish this sentence. "very obscure" -Steve
Sep 28 2016
On Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:The more I think about this submission, I feel like the benefits are quite slim.This is not and was not intended to be a glorious, incredible addition to the language. It is meant to shove D a couple inches further in the direction of modern programming constructs. Everywhere a programmer can use `else` instead of mucking about with a boolean success flag and having to make absolutely sure the code intended to handle a success state doesn't and will never be modified to throw an exception that the error handling code isn't designed for means less time spent on tedium, and less opportunity for programmer error. On Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:For example, should it be valid to use "else" without a catch?Yes. On Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:The boolean to indicate an exception was thrown is cumbersome, but not horrible. Having the compiler manage the boolean may make this cleaner (e.g. finally(bool thrown)), I like it better than the else suggestion.I think this would be an improvement over the current exception handling, but `else` is a pre-existing concept and making `finally` optionally accept a boolean this way tosses convention on its head, and not in a way I think is desireable. If what you're looking for is a clean solution, `finally(bool)` is definitely not it. Moreover, Idan's suggestions about scope sharing make sense to me and I don't think his line of thinking would be compatible with doing it the way you suggest.
Sep 28 2016
On Wednesday, 28 September 2016 at 20:18:06 UTC, pineapple wrote:This is not and was not intended to be a glorious, incredible addition to the language. It is meant to shove D a couple inches further in the direction of modern programming constructs. Everywhere a programmer can use `else` instead of mucking about with a boolean success flag and having to make absolutely sure the code intended to handle a success state doesn't and will never be modified to throw an exception that the error handling code isn't designed for means less time spent on tedium, and less opportunity for programmer error.Or, more concisely: Just because we have `for` doesn't mean we reject `foreach`. Just because we have `while` doesn't mean we reject `for`. Just because we have `goto` doesn't mean we reject `while`.
Sep 28 2016
On 09/28/2016 04:21 PM, pineapple wrote:On Wednesday, 28 September 2016 at 20:18:06 UTC, pineapple wrote:A DIP should stay as far away from this kind of argument as possible. Redundancy of existing features should not be used as precedent and justification for adding another redundant feature. The right angle here is to successfully present evidence that the frequency of a specific idiom/pattern is high enough to justify adding redundancy. +cc Dicebot to add this to the guidelines Thanks, AndreiThis is not and was not intended to be a glorious, incredible addition to the language. It is meant to shove D a couple inches further in the direction of modern programming constructs. Everywhere a programmer can use `else` instead of mucking about with a boolean success flag and having to make absolutely sure the code intended to handle a success state doesn't and will never be modified to throw an exception that the error handling code isn't designed for means less time spent on tedium, and less opportunity for programmer error.Or, more concisely: Just because we have `for` doesn't mean we reject `foreach`. Just because we have `while` doesn't mean we reject `for`. Just because we have `goto` doesn't mean we reject `while`.
Sep 29 2016
On 9/29/2016 7:32 AM, Andrei Alexandrescu wrote:A DIP should stay as far away from this kind of argument as possible. Redundancy of existing features should not be used as precedent and justification for adding another redundant feature.More generally, a problem with existing feature X is not a justification for introducing more instances of the problem. This line of justification occurs regularly.
Sep 29 2016
On 29.09.2016 19:35, Walter Bright wrote:On 9/29/2016 7:32 AM, Andrei Alexandrescu wrote:I posit you often just misunderstand what the argument is: It's more like: restriction A prevents B (B is what you think is bad), but it also prevents C and D (which are desirable), however, it does not even prevent E and F (which are arguably bad). Hence restriction A prevents many valid use cases without even effectively preventing "bad" usages.A DIP should stay as far away from this kind of argument as possible. Redundancy of existing features should not be used as precedent and justification for adding another redundant feature.More generally, a problem with existing feature X is not a justification for introducing more instances of the problem. This line of justification occurs regularly.
Sep 29 2016
On 9/28/16 4:18 PM, pineapple wrote:On Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:The main question to answer is how big is this "Everywhere". I've never needed it. This obviously isn't proof against, but the situation we are solving here seems very small. Is it worth adding a construct to the language and it seems here we are going to break valid code that already uses else after catch to mean something else?The more I think about this submission, I feel like the benefits are quite slim.This is not and was not intended to be a glorious, incredible addition to the language. It is meant to shove D a couple inches further in the direction of modern programming constructs. Everywhere a programmer can use `else` instead of mucking about with a boolean success flagOn Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:Again, try {this} else {that} looks like "try this if it works, else that", which is not what this really does. else only reads right if it follows catch.For example, should it be valid to use "else" without a catch?Yes.On Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:the pre-existing concept may work for Python, but not be OK for D (i.e. breaks valid code). The boolean concept is how you would implement it by hand, why does this toss it on its head? In fact, any code that requires this kind of flow already uses this mechanism, and can basically be updated to use the new concept by simply removing a few lines and changing finally to finally(bool).The boolean to indicate an exception was thrown is cumbersome, but not horrible. Having the compiler manage the boolean may make this cleaner (e.g. finally(bool thrown)), I like it better than the else suggestion.I think this would be an improvement over the current exception handling, but `else` is a pre-existing concept and making `finally` optionally accept a boolean this way tosses convention on its head, and not in a way I think is desireable. If what you're looking for is a clean solution, `finally(bool)` is definitely not it.Moreover, Idan's suggestions about scope sharing make sense to me and I don't think his line of thinking would be compatible with doing it the way you suggest.Declaring variables that you need in the right scopes is pretty straightforward. Having scopes magically continue around other separate scopes (catch scopes) doesn't look correct. I get why it's desired, but it doesn't look clean at all. -Steve
Sep 28 2016
On Wednesday, 28 September 2016 at 21:00:00 UTC, Steven Schveighoffer wrote:Declaring variables that you need in the right scopes is pretty straightforward. Having scopes magically continue around other separate scopes (catch scopes) doesn't look correct. I get why it's desired, but it doesn't look clean at all. -SteveConsider this: try { auto foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo does not exist here versus this: Foo foo; try { foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo exists here - it could be initialized, it could be not...
Sep 28 2016
On 9/28/2016 3:12 PM, Idan Arye wrote:Consider this: try { auto foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); }I agree with Steven. Having the 'else' continue on with a scope that is already closed by } is very weird and unsettling. You could argue that D already does this with static if: static if (x) { int x; } x = 3; and that disturbs some people. But it is conditional compilation, and no other way around it has been proposed, and it has major benefits. (C++'s static if proposal does not allow this, a decision that I predict they'll come to regret.) Adding more cases of this sort of thing should be approached with great trepidation, and is not justified if it is only a minor improvement.
Sep 28 2016
On Thursday, 29 September 2016 at 00:35:47 UTC, Walter Bright wrote:I agree with Steven. Having the 'else' continue on with a scope that is already closed by } is very weird and unsettling.SecondedBut it is conditional compilation, and no other way around it has been proposed, and it has major benefits. (C++'s static if proposal does not allow this, a decision that I predict they'll come to regret.)The C++ static_if will create a new scope? Huge mistake IMO. The fact that the static if doesn't create a new scope is a trick that's used a lot in D and Phobos specifically. Case in point: https://github.com/dlang/phobos/blob/a5e935370f5de590532bb5d12610c865343f56a9/std/string.d#L5859Adding more cases of this sort of thing should be approached with great trepidation, and is not justified if it is only a minor improvement.I agree; static if is different because it's a compile time feature and not a run time feature.
Sep 29 2016
On Wednesday, 28 September 2016 at 22:12:27 UTC, Idan Arye wrote:Foo foo; try { foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo exists here - it could be initialized, it could be not...And `Foo` could have ` disabled this()`, so you simply _can't_ declare it without initializing it (or use the dirty `Foo foo = Foo.init` workaround). But of course, that's a corner case...
Sep 29 2016
On 9/29/2016 4:45 AM, Marc Schütz wrote:And `Foo` could have ` disabled this()`, so you simply _can't_ declare it without initializing itFoo foo = void;
Sep 29 2016
On Thursday, 29 September 2016 at 17:47:41 UTC, Walter Bright wrote:On 9/29/2016 4:45 AM, Marc Schütz wrote:That's even worse. At least Foo.init would be deterministic.And `Foo` could have ` disabled this()`, so you simply _can't_ declare it without initializing itFoo foo = void;
Oct 02 2016
On 9/28/16 6:12 PM, Idan Arye wrote:On Wednesday, 28 September 2016 at 21:00:00 UTC, Steven Schveighoffer wrote:This is what I meant: { Foo foo; try { foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo exists here, but may or may not be correct. Don't use it. // in fact, don't write any code here. } // foo doesn't exist here, just like in other example. -SteveDeclaring variables that you need in the right scopes is pretty straightforward. Having scopes magically continue around other separate scopes (catch scopes) doesn't look correct. I get why it's desired, but it doesn't look clean at all.Consider this: try { auto foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo does not exist here versus this: Foo foo; try { foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo exists here - it could be initialized, it could be not...
Sep 29 2016
On Wednesday, 28 September 2016 at 21:00:00 UTC, Steven Schveighoffer wrote:Assuming for a minute that we want some form of DIP1002, we might be able to extend the `try` scope in an interesting way: try { auto f = foo(); } catch (Exception) { ... } finally (bool ok) { // true if no exception bar(); __guard (ok) f.baz(); f.baz(); // error: f not in scope } Here the guard statement is a runtime check of `ok`, but it has the compile-time effect of enabling the `try` scope to be extended. Obviously this is a bit extreme if it was the only use of the guard statement, but the guard statement could be useful in other situations too (e.g. non-null code checked at compile-time). Note that finally(bool) is more flexible than finally/else as you can interleave code arbitrarily. __guard makes it clearer something special is happening rather than just implicitly extending `try` scope in the `else` clause. Also, 'else' is not clear enough IMO.Moreover, Idan's suggestions about scope sharing make sense to me and I don't think his line of thinking would be compatible with doing it the way you suggest.Declaring variables that you need in the right scopes is pretty straightforward. Having scopes magically continue around other separate scopes (catch scopes) doesn't look correct. I get why it's desired, but it doesn't look clean at all.
Sep 29 2016
On Thursday, 29 September 2016 at 10:51:01 UTC, Nick Treleaven wrote:Note that finally(bool) is more flexible than finally/else as you can interleave code arbitrarily. __guard makes it clearer something special is happening rather than just implicitly extending `try` scope in the `else` clause. Also, 'else' is not clear enough IMO.While I think finally(bool) is a decent approach, the languages that currently integrate this concept into their error handling - Python and Ruby to my knowledge - all use `else`. Clarity is not a good argument, because those who are already proficient in languages other than D will expect the syntax to be consistent with other languages. It would be like some language using foolishly using `elsif instead of `else if`. (Dammit, Perl.)
Sep 29 2016
On 9/29/16 7:02 AM, pineapple wrote:On Thursday, 29 September 2016 at 10:51:01 UTC, Nick Treleaven wrote:In fact, finally(bool) can be extended to: enum ExceptionStatus { success = 0, caughtException = 1, uncaughtException = 2 } finally(ExceptionStatus) Which has also been requested in the past. -SteveNote that finally(bool) is more flexible than finally/else as you can interleave code arbitrarily. __guard makes it clearer something special is happening rather than just implicitly extending `try` scope in the `else` clause. Also, 'else' is not clear enough IMO.While I think finally(bool) is a decent approach, the languages that currently integrate this concept into their error handling - Python and Ruby to my knowledge - all use `else`. Clarity is not a good argument, because those who are already proficient in languages other than D will expect the syntax to be consistent with other languages. It would be like some language using foolishly using `elsif instead of `else if`. (Dammit, Perl.)
Sep 29 2016
On Thursday, 29 September 2016 at 10:51:01 UTC, Nick Treleaven wrote:Assuming for a minute that we want some form of DIP1002, we might be able to extend the `try` scope in an interesting way: try { auto f = foo(); } catch (Exception) { ... } finally (bool ok) { // true if no exception bar(); __guard (ok) f.baz(); f.baz(); // error: f not in scope }My 5 cents, let's play: try { ... } catch() { } catch() { } then { // I don't like idea to use 'else' very much. Please, don't use 'else' with try! ... } finally { } let's be more generic try { ... } catch() { } catch() { } then { ... } catch() { } catch() { } then { ... } catch() { } catch() { } ... finally { } (Hello from Javascript! But we have common scope here.) or use guard in a more obvious place try { // in this code exceptions are routed to attached catch() blocks catch(MyException); // yes, this guard looks as stand-alone catch() to avoid new keywords, for example. May be bad idea, I don't know. // oops, in this code MyException ignores attached catch() blocks because of guard } catch() { } catch() { } finally { } or make it again more generic try { // in this code exceptions are routed to attached catch() blocks as usual // ... but now catch() block can also be places inside of try block catch(MyException){ // process // goto finally } // oops, this code below of catch(MyException), so... } catch() { } catch() { } finally { } As for me, last variant is the most straightforward.
Sep 30 2016
On Wednesday, 28 September 2016 at 20:18:06 UTC, pineapple wrote:On Wednesday, 28 September 2016 at 17:56:13 UTC, Steven Schveighoffer wrote:Agree, programming should be fun, not struggle.The more I think about this submission, I feel like the benefits are quite slim.This is not and was not intended to be a glorious, incredible addition to the language. It is meant to shove D a couple inches further in the direction of modern programming constructs. Everywhere a programmer can use `else` instead of mucking about with a boolean success flag and having to make absolutely sure the code intended to handle a success state doesn't and will never be modified to throw an exception that the error handling code isn't designed for means less time spent on tedium, and less opportunity for programmer error.
Sep 28 2016
On 9/28/2016 12:47 AM, Andrei Alexandrescu wrote:* Please remove colloquialisms. Characterizations such as "fantastically useful" are unlikely to be a convincing motivator and have no place in a DIP. * The motivation section should showcase examples that currently are not possible or are contorted in D, followed by their alternative implementation using the proposed feature. At best, the example would be taken from existing code (e.g. found in dub, phobos, etc). Next best is code that defines a plausible artifact. * The motivation section should also hypothesize on why the feature did not get useful to show why D does need the feature even though it already has richer exception handing mechanisms by means of "scope". * The "Description" section should be more detailed and less casual. The grammar changes should be shown in a syntax similar to the current grammar definition. * [...] The proposal should be standalone and fully specified without knowing Python or perusing external links. * [...] Please focus on examples that are meaningful and easy with the feature, difficult without.These are great suggestions and apply generally. They should be added to the guide on doing a proper DIP.
Sep 28 2016
On Tuesday, 27 September 2016 at 09:30:10 UTC, Dicebot wrote:https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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:I support this addition because, while it's possible to mimic this behavior now, this makes code cleaner. I will also post some rationale from the Python docs: "The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try/except statement." https://docs.python.org/3/tutorial/errors.html#handling-exceptions
Sep 28 2016
On 9/28/16 12:19 PM, Jack Stouffer wrote:On Tuesday, 27 September 2016 at 09:30:10 UTC, Dicebot wrote:This rough count: git grep '^ *try' | wc -l reveals 187 uses of "try" in Phobos. Of these, how many could be improved? Looking into that and also on a selection of dub projects would strengthen the argument. Assertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).https://github.com/dlang/DIPs/blob/master/DIPs/DIP1002.md PR: https://github.com/dlang/DIPs/pull/43 Abstract: 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:I support this addition because, while it's possible to mimic this behavior now, this makes code cleaner.I will also post some rationale from the Python docs: "The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try/except statement." https://docs.python.org/3/tutorial/errors.html#handling-exceptionsPorting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages. Andrei
Sep 28 2016
On Wednesday, 28 September 2016 at 10:45:11 UTC, Andrei Alexandrescu wrote:Assertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).This is based on my anecdotal experience. I also posted an example in the original thread which was included in the DIP.Porting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages.It was already shown in this thread how scope statements do not achieve the same effect as the try/else statement; the point still stands.
Sep 28 2016
On Wednesday, 28 September 2016 at 10:50:00 UTC, Jack Stouffer wrote:On Wednesday, 28 September 2016 at 10:45:11 UTC, Andrei Alexandrescu wrote:Yes, scope can't immitate catch else without a flag. It doesn't follow that therefore we need catch else. What realistic code will be made significantly better by having it? Under what circumstances is structuring the code differently or using a flag so unacceptable that a new language feature is worth it? That's the question that needs answering.Assertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).This is based on my anecdotal experience. I also posted an example in the original thread which was included in the DIP.Porting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages.It was already shown in this thread how scope statements do not achieve the same effect as the try/else statement; the point still stands.
Sep 28 2016
On 9/28/16 6:50 AM, Jack Stouffer wrote:On Wednesday, 28 September 2016 at 10:45:11 UTC, Andrei Alexandrescu wrote:Thanks, Jack. Here I'm solely focused on making DIP1002 stronger so I've sent a number of suggestions that I believe would improve the proposal. Although you are free to argue here that in fact the proposal already is strong enough, this is not a "minimal requirements" setup in which a DIP is good to go as long as it passes a checklist. The demand here is elastic; the stronger the DIP, the better. Once submitted, if rejected, the only way to propose a similar feature is by authoring a new proposal with a completely novel perspective. So official review is an important milestone with a high bar. -- AndreiAssertions such as "makes the code cleaner" are likely to add value only if backed up by evidence (case studies, realistic examples).This is based on my anecdotal experience. I also posted an example in the original thread which was included in the DIP.Porting motivating arguments from other languages is helpful only if put in the context of D, e.g. Python does not have "scope" statements, which makes matters different across the two languages.It was already shown in this thread how scope statements do not achieve the same effect as the try/else statement; the point still stands.
Sep 29 2016
On Thursday, 29 September 2016 at 12:24:31 UTC, Andrei Alexandrescu wrote:Once submitted, if rejected, the only way to propose a similar feature is by authoring a new proposal with a completely novel perspective. So official review is an important milestone with a high bar. -- AndreiOk, I see where you're coming from, you want DIPs to be arguments in and of themselves. I was looking at them from a community prospective, where the DIP is argued on the forms like with module proposals.
Sep 29 2016
On Thursday, 29 September 2016 at 11:45:42 UTC, Marc Schütz wrote:On Wednesday, 28 September 2016 at 22:12:27 UTC, Idan Arye wrote:This is actually 100% of why I think scope sharing between `try`, `catch`, `finally`, and `else` statements deserves consideration. `Foo` should not have to be mutable or rebindable in order to handle its success or error state in the other statements. On Thursday, 29 September 2016 at 12:24:31 UTC, Andrei Alexandrescu wrote:Foo foo; try { foo = Foo(); } catch (FooCreationException) { // ... } else { foo.doSomethingWithFoo(); } // foo exists here - it could be initialized, it could be not...And `Foo` could have ` disabled this()`, so you simply _can't_ declare it without initializing it (or use the dirty `Foo foo = Foo.init` workaround). But of course, that's a corner case...Thanks, Jack. Here I'm solely focused on making DIP1002 stronger so I've sent a number of suggestions that I believe would improve the proposal. Although you are free to argue here that in fact the proposal already is strong enough, this is not a "minimal requirements" setup in which a DIP is good to go as long as it passes a checklist. The demand here is elastic; the stronger the DIP, the better. Once submitted, if rejected, the only way to propose a similar feature is by authoring a new proposal with a completely novel perspective. So official review is an important milestone with a high bar. -- AndreiI do appreciate the feedback, by the way, which is why I submitted the recent PR. One thing I'd point out: You rewrote my rewritten examples without using `else`, but as was stated immediately before I listed those examples:The best examples of code that can be more elegantly written using this `else` clause occur in application logic, such as the example described above where a values were read from sensors and saved to a server. However, there are a few places in Phobos that could be more readable and not require success flags if this new syntax were employed.
Sep 29 2016
On 09/29/2016 09:00 AM, pineapple wrote:One thing I'd point out: You rewrote my rewritten examples without using `else`, but as was stated immediately before I listed those examples:In order to make this kind of argument work, you need evidence. The sensor example is weak because (a) it comes with a rich context that is only vaguely explained; (b) it is not shown translated in current D; (c) it comes from private correspondence - at best it should be from a visible project. As of right now, the argument about application code being more helped than library code is purely speculative. That's why I also suggest looking at dub and github, which contain a good amount of D application code. You'd make a solid point if you showed how a few of those projects can be improved by the use of the proposed feature. AndreiThe best examples of code that can be more elegantly written using this `else` clause occur in application logic, such as the example described above where a values were read from sensors and saved to a server. However, there are a few places in Phobos that could be more readable and not require success flags if this new syntax were employed.
Sep 29 2016