www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - scope() statements and return

reply Shammah Chancellor <email domain.com> writes:
Per the documentation (http://dlang.org/statement.html) scope 
statements are not precluded from returning, but DMD does not allow for 
it.   Should the documentation be updated?

-S
Oct 02 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 10/02/2014 07:17 PM, Shammah Chancellor wrote:
 Per the documentation (http://dlang.org/statement.html) scope statements
 are not precluded from returning, but DMD does not allow for it.
 Should the documentation be updated?

 -S
Can you show a piece of code. The following quote says "may not exit with [...] return": "A scope(exit) or scope(success) statement may not exit with a throw, goto, break, continue, or return; nor may it be entered with a goto." Ali
Oct 02 2014
next sibling parent Shammah Chancellor <email domain.com> writes:
On 2014-10-03 03:23:24 +0000, Ali ehreli said:

 A scope(exit) or scope(success) statement may not exit with a throw, 
 goto, break, continue, or return; nor may it be entered with a goto
Derp. I did not see that. I was looking at the grammar on the top.
Oct 02 2014
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 3 October 2014 at 03:23:25 UTC, Ali Çehreli wrote:
 On 10/02/2014 07:17 PM, Shammah Chancellor wrote:
 Per the documentation (http://dlang.org/statement.html) scope 
 statements
 are not precluded from returning, but DMD does not allow for 
 it.
 Should the documentation be updated?

 -S
Can you show a piece of code. The following quote says "may not exit with [...] return": "A scope(exit) or scope(success) statement may not exit with a throw, goto, break, continue, or return; nor may it be entered with a goto." Ali
The throw thing is rather stupid, as the scope statement can call arbitrary function that can itself throw.
Oct 02 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 03 Oct 2014 04:40:53 +0000
deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 The throw thing is rather stupid, as the scope statement can call=20
 arbitrary function that can itself throw.
that's why you'd better use collectException() there, i presume. ;-) btw: shouldn't compiler check and reject code that calls no-nothrow functions in scope(...)? bug/ER?
Oct 02 2014
parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Friday, 3 October 2014 at 04:52:24 UTC, ketmar via 
Digitalmars-d wrote:
 On Fri, 03 Oct 2014 04:40:53 +0000
 deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 The throw thing is rather stupid, as the scope statement can 
 call arbitrary function that can itself throw.
that's why you'd better use collectException() there, i presume. ;-) btw: shouldn't compiler check and reject code that calls no-nothrow functions in scope(...)? bug/ER?
No, just like destructors can throw, scope statements can throw too. That's why we have exception chaining.
Oct 03 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/2/14, 8:23 PM, Ali Çehreli wrote:
 "A scope(exit) or scope(success) statement may not exit with a throw,
 goto, break, continue, or return; nor may it be entered with a goto."
Seems to me all these restrictions should be lifted. -- Andrei
Oct 03 2014
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Oct 03, 2014 at 10:50:39AM -0700, Andrei Alexandrescu via Digitalmars-d
wrote:
 On 10/2/14, 8:23 PM, Ali Çehreli wrote:
"A scope(exit) or scope(success) statement may not exit with a throw,
goto, break, continue, or return; nor may it be entered with a goto."
Seems to me all these restrictions should be lifted. -- Andrei
Please don't. It will lead to pathological behaviour. For example: int func() { scope(exit) return 1; return 0; } What does func() return? Better yet: int func() { scope(exit) return 1; scope(exit) return 2; return 0; } Worse yet: // What does this function do? What *should* it do?? int func() { scope(success) throw new Exception(""); scope(failure) return 1; return 0; } And: int func() { hahaha: scope(exit) goto hahaha; return 1; } Or: int func() { foreach (i; 0..10) { scope(exit) break; scope(exit) continue; return i; // hahahahahaha } return i; } And do we really want to get into this one: struct S { void opApply(scope void delegate(int) loopBody) { foreach (i; 0..10) { scope(success) continue; auto rc = loopBody(i); if (rc != 0) return rc; // ORLY?! } } } void main() { foreach (i; S.init) { scope(failure) continue; // what does this do? throw new Exception(""); } } T -- Береги платье снову, а здоровье смолоду.
Oct 03 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/3/14, 11:18 AM, H. S. Teoh via Digitalmars-d wrote:
 On Fri, Oct 03, 2014 at 10:50:39AM -0700, Andrei Alexandrescu via
Digitalmars-d wrote:
 On 10/2/14, 8:23 PM, Ali Çehreli wrote:
 "A scope(exit) or scope(success) statement may not exit with a throw,
 goto, break, continue, or return; nor may it be entered with a goto."
Seems to me all these restrictions should be lifted. -- Andrei
Please don't. It will lead to pathological behaviour. For example: int func() { scope(exit) return 1; return 0; } What does func() return?
1
 Better yet:

 	int func() {
 		scope(exit)
 			return 1;
 		scope(exit)
 			return 2;
 		return 0;
 	}
2
 Worse yet:

 	// What does this function do? What *should* it do??
 	int func() {
 		scope(success)
 			throw new Exception("");
 		scope(failure)
 			return 1;
 		return 0;
 	}
1
 And:

 	int func() {
 		hahaha: scope(exit) goto hahaha;
 		return 1;
 	}
infinite loop
 Or:

 	int func() {
 		foreach (i; 0..10) {
 			scope(exit) break;
 			scope(exit) continue;
 			return i; // hahahahahaha
 		}
 		return i;
 	}
compile error
 And do we really want to get into this one:

 	struct S {
 		void opApply(scope void delegate(int) loopBody) {
 			foreach (i; 0..10) {
 				scope(success) continue;
 				auto rc = loopBody(i);
 				if (rc != 0)
 					return rc; // ORLY?!
 			}
 		}
 	}
 	void main() {
 		foreach (i; S.init) {
 			scope(failure) continue; // what does this do?
 			throw new Exception("");
 		}
 	}
I guess I'm convinced it adds more complication than expressiveness! Andrei
Oct 03 2014
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 3 October 2014 at 19:35:21 UTC, Andrei Alexandrescu 
wrote:
 I guess I'm convinced it adds more complication than 
 expressiveness!
True for return, but throw is a stupid limitation( as it do not prevent the scope to throw at all, simply forc to hide it, which is only worse).
Oct 03 2014
next sibling parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 03:01:14 +0000
deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 True for return, but throw is a stupid limitation( as it do not=20
 prevent the scope to throw at all, simply forc to hide it, which=20
 is only worse).
scope(exit) { some-cleanup-code thisCanThrow(); some-more-cleanup-code } and what we should do with "some-more-cleanup-code" if "thisCanThrow" throws? it's breaks the promise that all cleanup code was executed prior to exiting. if i'm writing `collectException(thisCanThrow());`, i'm making my intents clear: "ok, i know that it can throw and i'm fully responsible to ignoring that here". yet silently allowing functions that throws in this context is disasterous, as it nullifies the promise on cleanup code. then i have to write such abominations: scope(exit) { some-cleanup-code scope(exit) some-more-cleanup-code; thisCanThrow(); } WUT?! this is hard to read and unnecessary complicated.
Oct 03 2014
next sibling parent reply "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Saturday, 4 October 2014 at 03:21:23 UTC, ketmar via 
Digitalmars-d wrote:
   scope(exit) {
     some-cleanup-code
     thisCanThrow();
     some-more-cleanup-code
   }

 and what we should do with "some-more-cleanup-code" if 
 "thisCanThrow"
 throws?
It is tricky if the throw implies that the caller to the cleanup should retry because of a timeout/deadlock, so the programmer have to analyze it and catch it if a retry is implied. So you need to catch in scope(exit) and check the coverage during semantic analysis. The alternatives are: 1. formally forbid throwing in all functions that closes/frees resources and use return values instead, but that is inconsistent with having exceptions in the first place... 2. not free resources, but use a manager object that frees them in the background, but that defeats having scope(exit) 3. remove exceptions from the language. Point 3 sounds nice. :-)
Oct 03 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 03:46:35 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d puremagic.com>
wrote:

 It is tricky if the throw implies that the caller to the cleanup=20
 should retry because of a timeout/deadlock
it shouldn't. exception during cleanup means "oh, i can't! i really-really-really can't!", not "ok, i'm busy, try again later." if some badly designed API does that -- write a wrapper.
Oct 03 2014
parent reply "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Saturday, 4 October 2014 at 04:29:06 UTC, ketmar via 
Digitalmars-d wrote:
 It is tricky if the throw implies that the caller to the 
 cleanup should retry because of a timeout/deadlock
it shouldn't. exception during cleanup means "oh, i can't! i really-really-really can't!", not "ok, i'm busy, try again later."
Should or should not, you have to make do with what you get from libraries. Network being temporarily unavailable is a good reason to throw when freeing a networked resource... Exceptions are made for recovery/retry/rollback.
 if some badly designed API does that -- write a wrapper.
So you need semantic analysis to ensure nothrow.
Oct 03 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 04:54:38 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d puremagic.com>
wrote:

 Should or should not, you have to make do with what you get from=20
 libraries.
wrapper is the answer.
 Network being temporarily unavailable is a good reason=20
 to throw when freeing a networked resource...
that means "oh, i really-really-really can't!" there is no guarantees that network will be up again soon.
 So you need semantic analysis to ensure nothrow.
we have it, and we have that nice "nothrow" attribute.
Oct 03 2014
parent reply "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Saturday, 4 October 2014 at 05:05:00 UTC, ketmar via 
Digitalmars-d wrote:
 On Sat, 04 Oct 2014 04:54:38 +0000
 Ola Fosheim Grostad via Digitalmars-d 
 <digitalmars-d puremagic.com>
 wrote:

 Should or should not, you have to make do with what you get 
 from libraries.
wrapper is the answer.
I dont disagree, but the language spec says that you cannot catch in a finally block... (which is the same as scope(exit).
Oct 03 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 05:22:10 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d puremagic.com>
wrote:

 Should or should not, you have to make do with what you get=20
 from libraries.
wrapper is the answer.
I dont disagree, but the language spec says that you cannot catch=20 in a finally block... (which is the same as scope(exit).
and... wrapper is the answer! ;-) void myWrapper () nothrow { try throwItAtMe(); catch (LovelyException) {} } scope(exit) myWrapper(); this is perfectly legal, as we not cathcing anything in scope(exit).
Oct 03 2014
parent reply "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Saturday, 4 October 2014 at 05:33:29 UTC, ketmar via 
Digitalmars-d wrote:
   void myWrapper () nothrow {
     try throwItAtMe(); catch (LovelyException) {}
   }


   scope(exit) myWrapper();


 this is perfectly legal, as we not cathcing anything in 
 scope(exit).
Why should these two cases be treated different? Makes no sense,
Oct 03 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 05:37:14 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d puremagic.com>
wrote:

 Why should these two cases be treated different? Makes no sense,
'cause `MyWrapper` promises to nothrow. you can't make such promise for try-block. i.e. `MyWrapper` promises that the only exception that can be thrown is `LovelyException`, and it's catched, thus `MyWrapper` is marked "nothrow". you can't attach such mark to try/catch, even if you know for sure that you catched 'em all. it's a matter of style.
Oct 03 2014
parent reply "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Saturday, 4 October 2014 at 05:54:20 UTC, ketmar via 
Digitalmars-d wrote:,
 'cause `MyWrapper` promises to nothrow. you can't make such 
 promise for
 try-block.
If finally does imply nothrow then the try-block implies it too. No difference from a wrapper.
 i.e. `MyWrapper` promises that the only exception that can be 
 thrown is
 `LovelyException`, and it's catched, thus `MyWrapper` is marked
 "nothrow". you can't attach such mark to try/catch, even if you 
 know
 for sure that you catched 'em all. it's a matter of style.
Nah, it is a matter of ad hoc design and implementation that needs more rigour.
Oct 03 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 05:58:47 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d puremagic.com>
wrote:

 Nah, it is a matter of ad hoc design and implementation that=20
 needs more rigour.
something like 'final try' can be fun. 'try' says that it can catch only some kinds of exceptions, and 'final try' promises that there will be no exceptions that aren't in catch() block. besides, any exception that 'final try' is not catching should abort the process. do you mind to fill ER? it will be rejected, but hey, we can start a little competiion here! ;-)
Oct 03 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Saturday, 4 October 2014 at 06:28:52 UTC, ketmar via 
Digitalmars-d wrote:
 do you mind to fill ER? it will be rejected, but hey, we can 
 start a
 little competiion here! ;-)
Triathlon isn't really my thing... So I am only participating in the patching-competition. :-)
Oct 04 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/3/14, 11:28 PM, ketmar via Digitalmars-d wrote:
 On Sat, 04 Oct 2014 05:58:47 +0000
 Ola Fosheim Grostad via Digitalmars-d <digitalmars-d puremagic.com>
 wrote:

 Nah, it is a matter of ad hoc design and implementation that
 needs more rigour.
something like 'final try' can be fun. 'try' says that it can catch only some kinds of exceptions, and 'final try' promises that there will be no exceptions that aren't in catch() block. besides, any exception that 'final try' is not catching should abort the process. do you mind to fill ER? it will be rejected, but hey, we can start a little competiion here! ;-)
There's no interesting way to check this because functions don't list the exceptions they might throw (like Java does). -- Andrei
Oct 04 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 14:48:26 -0700
Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com>
wrote:

 There's no interesting way to check this because functions don't list=20
 the exceptions they might throw (like Java does). -- Andrei
sure there is no way to check. this 'final try' helper is required exactly 'cause compiler can't do necessary checks, and programmer can assure compiler that "it's ok, we'll catching 'em all here!" this way 'try/catch' will not be "nothrow", only 'final try/catch'. and there will be *nothing* that can be catched outside of 'final try/catch'. i.e. if something was not catched in 'final', it's a fatal bug. crash-boom-band, we are dead. but i don't want to create ER, 'cause it will be rejected. it implies code breaking ("simple" try/catch can't be used in 'nothrow' functions anymore), and ERs with code breaking feature have no chances.
Oct 04 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/05/2014 08:01 AM, ketmar via Digitalmars-d wrote:
 On Sat, 04 Oct 2014 14:48:26 -0700
 Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com>
 wrote:

 There's no interesting way to check this because functions don't list
 the exceptions they might throw (like Java does). -- Andrei
sure there is no way to check. this 'final try' helper is required exactly 'cause compiler can't do necessary checks, and programmer can assure compiler that "it's ok, we'll catching 'em all here!" this way 'try/catch' will not be "nothrow", only 'final try/catch'. and there will be *nothing* that can be catched outside of 'final try/catch'. i.e. if something was not catched in 'final', it's a fatal bug. crash-boom-band, we are dead. but i don't want to create ER, 'cause it will be rejected. it implies code breaking ("simple" try/catch can't be used in 'nothrow' functions anymore), and ERs with code breaking feature have no chances.
What's the point anyway? try{ ... } catch assert(0);
Oct 07 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tue, 07 Oct 2014 14:59:52 +0200
Timon Gehr via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 What's the point anyway?
non-final try/catch will not make function "nothrow".
Oct 07 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/07/2014 03:57 PM, ketmar via Digitalmars-d wrote:
 On Tue, 07 Oct 2014 14:59:52 +0200
 Timon Gehr via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 What's the point anyway?
non-final try/catch will not make function "nothrow".
void doStuff(){ } void main() nothrow{ try{ doStuff(); } catch assert(0); }
Oct 07 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tue, 07 Oct 2014 16:08:33 +0200
Timon Gehr via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 What's the point anyway?
non-final try/catch will not make function "nothrow".
i'm talking about my proposal, where non-final try/catch will not make function nothrow, only 'final try' will do. and anything that not catched in this 'final' will abort the program immediately, without any tries to do unwinding or executing scope() statements.
Oct 07 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/07/2014 04:23 PM, ketmar via Digitalmars-d wrote:
 On Tue, 07 Oct 2014 16:08:33 +0200
 Timon Gehr via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 What's the point anyway?
non-final try/catch will not make function "nothrow".
import core.exception; void doStuff(){ } void main() nothrow{ try{ doStuff(); } catch(UnicodeException){ } } Error: function D main 'main' is nothrow yet may throw
 i'm talking about my proposal, where non-final try/catch will not make
 function nothrow, only 'final try' will do.
I.e. additional annotation overhead without a point?
 and anything that not
 catched in this 'final' will abort the program immediately, without any
 tries to do unwinding or executing scope() statements.
import core.stdc.stdlib; void doStuff(){ throw new Exception(""); } void main() nothrow{ scope(exit) assert(0); try{ doStuff(); } catch(Exception){ exit(2); } }
Oct 07 2014
parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tue, 07 Oct 2014 16:34:12 +0200
Timon Gehr via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 import core.exception;
=20
 void doStuff(){ }
=20
 void main() nothrow{
      try{ doStuff(); }
      catch(UnicodeException){ }
 }
=20
 Error: function D main 'main' is nothrow yet may throw
that's not the same as 'final try': anything that is not UnicodeException or it's descendant will pass thru. for 'final try' anything other will crash the program immediately. no, 'assert(0)' is not the same.
 i'm talking about my proposal, where non-final try/catch will not
 make function nothrow, only 'final try' will do.
I.e. additional annotation overhead without a point?
with a point. you even quoted it.
 and anything that not
 catched in this 'final' will abort the program immediately, without
 any tries to do unwinding or executing scope() statements.
=20 import core.stdc.stdlib; =20 void doStuff(){ throw new Exception(""); } =20 void main() nothrow{ scope(exit) assert(0); try{ doStuff(); } catch(Exception){ exit(2); } }
i see *alot* of overhead here. and 'exit()', which will not show what exception was thrown. yes, we can print this info manually -- adding even more overhead. with 'final try' reader immediately recognizes writer's intentions.
Oct 07 2014
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 4 October 2014 at 03:21:23 UTC, ketmar via 
Digitalmars-d wrote:
 On Sat, 04 Oct 2014 03:01:14 +0000
 deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 True for return, but throw is a stupid limitation( as it do 
 not prevent the scope to throw at all, simply forc to hide it, 
 which is only worse).
scope(exit) { some-cleanup-code thisCanThrow(); some-more-cleanup-code } and what we should do with "some-more-cleanup-code" if "thisCanThrow" throws? it's breaks the promise that all cleanup code was executed prior to exiting. if i'm writing `collectException(thisCanThrow());`, i'm making my intents clear: "ok, i know that it can throw and i'm fully responsible to ignoring that here". yet silently allowing functions that throws in this context is disasterous, as it nullifies the promise on cleanup code. then i have to write such abominations: scope(exit) { some-cleanup-code scope(exit) some-more-cleanup-code; thisCanThrow(); } WUT?! this is hard to read and unnecessary complicated.
Write this in sepeareted scope statement?. problem solved. Also, we have exception chaining, so that's all good.
Oct 03 2014
next sibling parent "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Saturday, 4 October 2014 at 04:47:46 UTC, deadalnix wrote:
 Also, we have exception chaining, so that's all good.
Exception chaining just means that you build a linked list recording the history when rethrowing a different type of exception in a catch block. How does that help?
Oct 03 2014
prev sibling parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 04 Oct 2014 04:47:44 +0000
deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Write this in sepeareted scope statement?. problem solved.
i don't agree. it makes excessive noise for nothing. and it breaking the implied promise "all cleanup code will be executed on exit". it's easy to miss something that can throw in scope(...). so the only other option is to write this noisy code: scope(exit) firstCall(); scope(exit) secondCall(); scope(exit) thirdCall(); ...and so on. and double-check if everything was really executed -- just in case. 'cause there is no promise to execute cleanup code anymore.
Oct 03 2014
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdan.org> writes:
"deadalnix" <deadalnix gmail.com> wrote:
 On Friday, 3 October 2014 at 19:35:21 UTC, Andrei Alexandrescu wrote:
 I guess I'm convinced it adds more complication than > expressiveness!
 
True for return, but throw is a stupid limitation( as it do not prevent the scope to throw at all, simply forc to hide it, which is only worse).
Yah throw would be nice and helpful. -- Andrei
Oct 03 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/3/14, 8:01 PM, deadalnix wrote:
 On Friday, 3 October 2014 at 19:35:21 UTC, Andrei Alexandrescu wrote:
 I guess I'm convinced it adds more complication than expressiveness!
True for return, but throw is a stupid limitation( as it do not prevent the scope to throw at all, simply forc to hide it, which is only worse).
Yah, nonlocal returns are odd but throw should be perfectly fine (and good to have). -- Andrei
Oct 04 2014
parent Shammah Chancellor <email domain.com> writes:
On 2014-10-04 21:44:43 +0000, Andrei Alexandrescu said:

 On 10/3/14, 8:01 PM, deadalnix wrote:
 On Friday, 3 October 2014 at 19:35:21 UTC, Andrei Alexandrescu wrote:
 I guess I'm convinced it adds more complication than expressiveness!
 
True for return, but throw is a stupid limitation( as it do not prevent the scope to throw at all, simply forc to hide it, which is only worse).
Yah, nonlocal returns are odd but throw should be perfectly fine (and good to have). -- Andrei
They were removed because they stop the propigation of Errors when and if they were to throw. This was already discussed quite a bit months ago. My original message was not intended to respawn the debate. Here's the dbug: https://issues.dlang.org/show_bug.cgi?id=11574 I'm not sure why it's still open actually. -Shammah
Oct 04 2014
prev sibling parent reply Shammah Chancellor <email domain.com> writes:
On 2014-10-03 19:35:31 +0000, Andrei Alexandrescu said:

 Better yet:
 
 	int func() {
 		scope(exit)
 			return 1;
 		scope(exit)
 			return 2;
 		return 0;
 	}
2
That should return 1 as the return 1 is the last thing to execute. SDC currently doesn't disallow this and correctly produces 1. It'll be lowered as such: int foo2() { try { try { return 0; } finally { return 2; } } finally { return 1; } }
 
 Worse yet:
 
 	// What does this function do? What *should* it do??
 	int func() {
 		scope(success)
 			throw new Exception("");
 		scope(failure)
 			return 1;
 		return 0;
 	}
1
This throws an exception, as it's already outside of the scope(failure) block and into the finally for success; -S
Oct 03 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Sat, Oct 04, 2014 at 01:08:38AM -0400, Shammah Chancellor via Digitalmars-d
wrote:
 On 2014-10-03 19:35:31 +0000, Andrei Alexandrescu said:
[...]
Worse yet:

	// What does this function do? What *should* it do??
	int func() {
		scope(success)
			throw new Exception("");
		scope(failure)
			return 1;
		return 0;
	}
1
This throws an exception, as it's already outside of the scope(failure) block and into the finally for success;
[...] And if you switched the two scope statements? I think you guys are missing the point... The point is that it's ridiculous for the function to return one thing, only for the scope statement to modify that return value after the fact in a way that totally obfuscates the code. int func() { lots(); of(); scope(exit) return 1; code(); inBetween(); // What does this function return? Yes, "obviously" it // returns 1. Right. return 0; } Similarly, allowing scope to do arbitrary things will easily turn your loops into spaghetti code: foreach (i; 0 .. 10) { scope(exit) break; scope(success) continue; if (i==5) break; // Yeah right, this doesn't actually break // (even though it's totally broken :-P) scope(failure) return; if (i==8) throw new Exception(); // Yeah right, this is just a dainbramaged way // of breaking the loop } writeln("You know I actually get run?"); The only use of allowing these disruptive flow control constructs in scope statements, that I can see, is to facilitate in writing entries for the International Obfuscated D Code Contest. T -- Маленькие детки - маленькие бедки.
Oct 03 2014
parent reply Shammah Chancellor <email domain.com> writes:
On 2014-10-04 06:09:39 +0000, H. S. Teoh via Digitalmars-d said:

 On Sat, Oct 04, 2014 at 01:08:38AM -0400, Shammah Chancellor via 
 Digitalmars-d wrote:
 On 2014-10-03 19:35:31 +0000, Andrei Alexandrescu said:
[...]
 Worse yet:
 
 	// What does this function do? What *should* it do??
 	int func() {
 		scope(success)
 			throw new Exception("");
 		scope(failure)
 			return 1;
 		return 0;
 	}
1
This throws an exception, as it's already outside of the scope(failure) block and into the finally for success;
[...] And if you switched the two scope statements? I think you guys are missing the point... The point is that it's ridiculous for the function to return one thing, only for the scope statement to modify that return value after the fact in a way that totally obfuscates the code. int func() { lots(); of(); scope(exit) return 1; code(); inBetween(); // What does this function return? Yes, "obviously" it // returns 1. Right. return 0; } Similarly, allowing scope to do arbitrary things will easily turn your loops into spaghetti code: foreach (i; 0 .. 10) { scope(exit) break; scope(success) continue; if (i==5) break; // Yeah right, this doesn't actually break // (even though it's totally broken :-P) scope(failure) return; if (i==8) throw new Exception(); // Yeah right, this is just a dainbramaged way // of breaking the loop } writeln("You know I actually get run?"); The only use of allowing these disruptive flow control constructs in scope statements, that I can see, is to facilitate in writing entries for the International Obfuscated D Code Contest. T
Didn't miss anything. I was responding to Andrei such that he might think it's not so straightforward to evaluate that code. I am with you on this. It was my original complaint months ago that resulted in this being disallowed behavior. Specifically because you could stop error propigation by accident even though you did not intend to prevent their propigation. e.g: int main() { scope(exit) return 0; assert(false, "whoops!"); } -S
Oct 04 2014
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 4 October 2014 at 18:42:05 UTC, Shammah Chancellor 
wrote:
 Didn't miss anything.  I was responding to Andrei such that he 
 might think it's not so straightforward to evaluate that code.
  I am with you on this.  It was my original complaint months 
 ago that resulted in this being disallowed behavior.  
 Specifically because you could stop error propigation by 
 accident even though you did not intend to prevent their 
 propigation.  e.g:

 int main()
 {
 	scope(exit) return 0;
 	assert(false, "whoops!");
 }

 -S
Isn't this the "should scope(exit/failure) catch Error" issue though? In theory, you should seldom ever catch Errors. I don't understand why "scope(exit)" are catching them.
Oct 05 2014
next sibling parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sun, 05 Oct 2014 11:28:59 +0000
monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 In theory, you should seldom ever catch Errors. I don't=20
 understand why "scope(exit)" are catching them.
'cause scope(exit) keeps the promise to execute cleanup code before exiting code block?
Oct 05 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 5 October 2014 at 12:36:30 UTC, ketmar via 
Digitalmars-d wrote:
 On Sun, 05 Oct 2014 11:28:59 +0000
 monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 In theory, you should seldom ever catch Errors. I don't 
 understand why "scope(exit)" are catching them.
'cause scope(exit) keeps the promise to execute cleanup code before exiting code block?
Promises hold provided the precondition your program is in a valid state. Having an Error invalidates that precondition, hence voids that promise. RAII also makes the promise, but you don't see Errors giving much of a fuck about that.
Oct 05 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sun, 05 Oct 2014 14:53:37 +0000
monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Promises hold provided the precondition your program is in a=20
 valid state. Having an Error invalidates that precondition, hence=20
 voids that promise.
so Error should not be catchable and should crash immidiately, without any unwinding. as long as Errors are just another kind of exception, the promise must be kept.
Oct 05 2014
next sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Sunday, 5 October 2014 at 15:03:08 UTC, ketmar via 
Digitalmars-d wrote:
 so Error should not be catchable and should crash immidiately, 
 without
 any unwinding. as long as Errors are just another kind of 
 exception,
 the promise must be kept.
I find it strange if you cannot recover from out-of-memory-error. The common trick is to preallocate a bulk of memory, then free it when you throw the out of memory exception so that you can unwind. When destroying the out-of-memory-object you need to reallocate the bulk of memory. I also find the D terminology confusing, one should avoid redefining terms. Does D have exception chaining? The language spec seems to imply that finally swallows thrown exceptions if another exception A is running and stuff them in a bag in the A exception. This is kind of dangerous since you hide potentially serious exceptions this way and it is not what I think of as exception chaining. To me exception chaining is preserve the exception chain on re-throws (like preserving the call stack). So yep, ketmar, you are right. You should probably not be able to throw in finally without catching it, and you should be able to do a catch all without wrapping it up in a function. The alternatives such as the mechanics described in the language specs will lead to unreliable exception handling and poor recovery strategies IMO.
Oct 05 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim Grøstad 
wrote:
 Does D have exception chaining?
Though it seems to do more harm then good so far.
Oct 05 2014
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/5/14, 9:42 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim Grøstad wrote:
 Does D have exception chaining?
Though it seems to do more harm then good so far.
What harm does it do? -- Andrei
Oct 05 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 5 October 2014 at 17:03:07 UTC, Andrei Alexandrescu 
wrote:
 On 10/5/14, 9:42 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim Grøstad 
 wrote:
 Does D have exception chaining?
Though it seems to do more harm then good so far.
What harm does it do? -- Andrei
Good chunk of issues with pre-allocated exceptions (and possible cycles in reference counted ones) comes from the chanining possibility. At the same time I have yet to see it actively used as a feature. Doesn't mean it is bad thing, just not used wide enough to compensate for trouble right now.
Oct 05 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/5/2014 10:09 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 17:03:07 UTC, Andrei Alexandrescu wrote:
 On 10/5/14, 9:42 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim Grøstad wrote:
 Does D have exception chaining?
Though it seems to do more harm then good so far.
What harm does it do? -- Andrei
Good chunk of issues with pre-allocated exceptions (and possible cycles in reference counted ones) comes from the chanining possibility. At the same time I have yet to see it actively used as a feature. Doesn't mean it is bad thing, just not used wide enough to compensate for trouble right now.
FWIW, I'm skeptical as well of the value of chaining relative to its cost in complexity.
Oct 06 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Monday, 6 October 2014 at 07:28:22 UTC, Walter Bright wrote:
 FWIW, I'm skeptical as well of the value of chaining relative 
 to its cost in complexity.
Python 3 has two fields: "__cause__" and "__context__". The cause field is used for explicit chaining on re-throws. Can be useful for diagnostics and is trouble free. The context field is used for preserving exceptions that are unfortunately overruled by subsequent throws. Which can lead to missed clean-up handling. :-/
Oct 06 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/6/14, 12:27 AM, Walter Bright wrote:
 On 10/5/2014 10:09 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 17:03:07 UTC, Andrei Alexandrescu wrote:
 On 10/5/14, 9:42 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim Grøstad wrote:
 Does D have exception chaining?
Though it seems to do more harm then good so far.
What harm does it do? -- Andrei
Good chunk of issues with pre-allocated exceptions (and possible cycles in reference counted ones) comes from the chanining possibility. At the same time I have yet to see it actively used as a feature. Doesn't mean it is bad thing, just not used wide enough to compensate for trouble right now.
FWIW, I'm skeptical as well of the value of chaining relative to its cost in complexity.
It's one of those designs in which there's little room to turn. We wanted to (a) allow destructors to throw, (b) conserve information. Offering access to all exceptions caught was a natural consequence. -- Andrei
Oct 06 2014
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 6 October 2014 at 13:48:07 UTC, Andrei Alexandrescu 
wrote:
 On 10/6/14, 12:27 AM, Walter Bright wrote:
 On 10/5/2014 10:09 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 17:03:07 UTC, Andrei 
 Alexandrescu wrote:
 On 10/5/14, 9:42 AM, Dicebot wrote:
 On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim 
 Grøstad wrote:
 Does D have exception chaining?
Though it seems to do more harm then good so far.
What harm does it do? -- Andrei
Good chunk of issues with pre-allocated exceptions (and possible cycles in reference counted ones) comes from the chanining possibility. At the same time I have yet to see it actively used as a feature. Doesn't mean it is bad thing, just not used wide enough to compensate for trouble right now.
FWIW, I'm skeptical as well of the value of chaining relative to its cost in complexity.
It's one of those designs in which there's little room to turn. We wanted to (a) allow destructors to throw, (b) conserve information. Offering access to all exceptions caught was a natural consequence. -- Andrei
Well, then again, even that promise isn't really held. If your "catch" throws an exception, then the new exception simply "squashes" replaces the old one: //---- catch (Exception e) { thisMightThrow(); //Lose "e" here throw e; } //---- I've seen literally no-one ever chain exceptions once one has been caught. Not even druntime does it. For example, if an exception occurs during a static array construction, this triggers the destruction of already constructed items. If one of *those* fails, then the cleanup loop terminates (without cleaning the rest of the items mind you). And the user is greeted with a "Object destruction failed", even though the array was never constructed to begin with! There's merit in the goal, but I don't think the current design has achieved it.
Oct 06 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/6/14, 7:24 AM, monarch_dodra wrote:
 If your "catch" throws an exception, then the new exception simply
 "squashes" replaces the old one:

 //----
 catch (Exception e)
 {
      thisMightThrow(); //Lose "e" here
      throw e;
 }
 //----
That's code under library/user control, I'm talking about the responsibility of the language. -- Andrei
Oct 06 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 6 October 2014 at 14:54:21 UTC, Andrei Alexandrescu 
wrote:
 On 10/6/14, 7:24 AM, monarch_dodra wrote:
 If your "catch" throws an exception, then the new exception 
 simply
 "squashes" replaces the old one:

 //----
 catch (Exception e)
 {
     thisMightThrow(); //Lose "e" here
     throw e;
 }
 //----
That's code under library/user control, I'm talking about the responsibility of the language. -- Andrei
Right. but if correct usage is so cumbersome no one does it right, then it is 's/the responsibility/a flaw/' of the language. Are we advocating then that code under user control should systematically look like this? catch (Exception e) { try { thisMightThrow(); //Lose "e" here } catch(Exception ee) { findLast(e).next = ee; //because e.next might } throw e; } Honestly, a good middle ground is to ditch chaining, but allow multiple exceptions thrown at once. Subsequent Exceptions/Errors will just be lost (sorry), with the exception that an Error will override an Exception. For the sake of argument, do you have any examples where a program has used chaining?
Oct 06 2014
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/6/14, 9:55 AM, monarch_dodra wrote:
 On Monday, 6 October 2014 at 14:54:21 UTC, Andrei Alexandrescu wrote:
 On 10/6/14, 7:24 AM, monarch_dodra wrote:
 If your "catch" throws an exception, then the new exception simply
 "squashes" replaces the old one:

 //----
 catch (Exception e)
 {
     thisMightThrow(); //Lose "e" here
     throw e;
 }
 //----
That's code under library/user control, I'm talking about the responsibility of the language. -- Andrei
Right. but if correct usage is so cumbersome no one does it right, then it is 's/the responsibility/a flaw/' of the language. Are we advocating then that code under user control should systematically look like this? catch (Exception e) { try { thisMightThrow(); //Lose "e" here } catch(Exception ee) { findLast(e).next = ee; //because e.next might } throw e; }
Only if it needs to save that information. As far as the core language is concerned, once an exception has been caught and made available to the user, it's up to the user what to do with it. The point of chaining is to not render information inaccessible to user no matter what they do. This is a fairly basic remark.
 Honestly, a good middle ground is to ditch chaining, but allow multiple
 exceptions thrown at once. Subsequent Exceptions/Errors will just be
 lost (sorry), with the exception that an Error will override an Exception.
If I redesigned D's exceptions, I'd change a bunch of stuff before that.
 For the sake of argument, do you have any examples where a program has
 used chaining?
Whenever an exception is converted to a string, the chained exceptions should be part of it too. Andrei
Oct 06 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 6 October 2014 at 16:59:35 UTC, Andrei Alexandrescu 
wrote:
 Whenever an exception is converted to a string, the chained 
 exceptions should be part of it too.
On Monday, 6 October 2014 at 17:12:00 UTC, Jakob Ovrum wrote:
 However, the whole point is implicit chaining, which is where 
 the language and runtime kicks in. Look through your own 
 scope(exit|failure) blocks and struct destructors - are they 
 all nothrow?

 If not, you are using exception chaining.
Hum... But arguably, that's just exception chaining "happening". Do you have any examples of someone actually "dealing" with all the exceptions in a chain in a catch, or actually using the information in a manner that is more than just printing?
Oct 07 2014
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 7 October 2014 at 07:36:56 UTC, monarch_dodra wrote:
 "happening". Do you have any examples of someone actually 
 "dealing" with all the exceptions in a chain in a catch, or 
 actually using the information in a manner that is more than 
 just printing?
I've never used it myself in real code, but I think the "swallow concurrent exceptions" is very difficult to reason about, because it might be a side effect and not a primary cause. Capturing the origin for a rethrow is potentially useful since it can tell you whether you should retry or not. If the cause is a "network unavailable" then you might want to retry. If the cause is a type error you might want to log an error and bail out.
Oct 07 2014
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/7/14, 12:36 AM, monarch_dodra wrote:
 Hum... But arguably, that's just exception chaining "happening". Do you
 have any examples of someone actually "dealing" with all the exceptions
 in a chain in a catch, or actually using the information in a manner
 that is more than just printing?
No. But that doesn't mean anything; all uses of exceptions I know of are used for just printing. -- Andrei
Oct 07 2014
parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 07 Oct 2014 14:39:06 +0100, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 10/7/14, 12:36 AM, monarch_dodra wrote:
 Hum... But arguably, that's just exception chaining "happening". Do you
 have any examples of someone actually "dealing" with all the exceptions
 in a chain in a catch, or actually using the information in a manner
 that is more than just printing?
No. But that doesn't mean anything; all uses of exceptions I know of are used for just printing. -- Andrei
[not just for printing] 1. I catch a ChangeConflictException and attempt some basic automatic conflict resolution (i.e. column has changed in the database, but I have not changed the local version then merge the value from database) [examining the chain] 2. I catch Exception then test if "ex is TransactionException" AND if "ex.InnerException is TimeoutException" (AKA first in chain) then raise a different sort of alert (for our GUI to display). (FYI the reason I don't have a separate catch block for TransactionException specifically is that it would involve duplicating all the cleanup I am doing in this catch block, all for a 1 line "raise a different alert" call - it just didn't seem worth it) R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Oct 08 2014
prev sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 6 October 2014 at 16:55:39 UTC, monarch_dodra wrote:
 For the sake of argument, do you have any examples where a 
 program has used chaining?
I use explicit chaining in a couple of my libraries, i.e. code like: --- try foo(); catch(FooException e) { throw new BarException("foobar", e); } --- However, the whole point is implicit chaining, which is where the language and runtime kicks in. Look through your own scope(exit|failure) blocks and struct destructors - are they all nothrow? If not, you are using exception chaining.
Oct 06 2014
parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 6 October 2014 at 17:12:00 UTC, Jakob Ovrum wrote:
 On Monday, 6 October 2014 at 16:55:39 UTC, monarch_dodra wrote:
 For the sake of argument, do you have any examples where a 
 program has used chaining?
I use explicit chaining in a couple of my libraries, i.e. code like: --- try foo(); catch(FooException e) { throw new BarException("foobar", e); } --- However, the whole point is implicit chaining, which is where the language and runtime kicks in. Look through your own scope(exit|failure) blocks and struct destructors - are they all nothrow? If not, you are using exception chaining.
I think this is supposed to chain the other way around.
Oct 06 2014
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Monday, 6 October 2014 at 13:48:07 UTC, Andrei Alexandrescu
wrote:
 It's one of those designs in which there's little room to turn. 
 We wanted to (a) allow destructors to throw, (b) conserve 
 information. Offering access to all exceptions caught was a 
 natural consequence. -- Andrei
Note that if we reverse the chaining (like java does), then the loop problem mostly disappear. It is still possible to create it, you you got to actively look for it.
Oct 06 2014
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/6/14, 7:25 PM, deadalnix wrote:
 On Monday, 6 October 2014 at 13:48:07 UTC, Andrei Alexandrescu
 wrote:
 It's one of those designs in which there's little room to turn. We
 wanted to (a) allow destructors to throw, (b) conserve information.
 Offering access to all exceptions caught was a natural consequence. --
 Andrei
Note that if we reverse the chaining (like java does), then the loop problem mostly disappear. It is still possible to create it, you you got to actively look for it.
I knew Python has chaining but not Java. Got a reference handy? My searches suggest that in Java that's a manual technique only. -- Andrei
Oct 06 2014
parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 October 2014 at 03:19:06 UTC, Andrei Alexandrescu 
wrote:
 Note that if we reverse the chaining (like java does), then the
 loop problem mostly disappear. It is still possible to create 
 it,
 you you got to actively look for it.
I knew Python has chaining but not Java. Got a reference handy? My searches suggest that in Java that's a manual technique only. -- Andrei
Yes there is no language magic to it in java. It is by convention.
Oct 07 2014
prev sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Sunday, 5 October 2014 at 16:42:38 UTC, Dicebot wrote:

 Though it seems to do more harm then good so far.
Hm, so the next field is used for two different purposes? Both for capturing the original exception on a rethrow and for capturing concurrent exceptions originating in a finally block? That is messy. I personally find regular exceptions overcomplicated for a system level language. I think I'd rather allocate resources through manager objects and release on runtime-registered landing pads, allowing the omission of frame-pointers.
Oct 05 2014
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim Grøstad 
wrote:
 On Sunday, 5 October 2014 at 15:03:08 UTC, ketmar via 
 Digitalmars-d wrote:
 so Error should not be catchable and should crash immidiately, 
 without
 any unwinding. as long as Errors are just another kind of 
 exception,
 the promise must be kept.
I find it strange if you cannot recover from out-of-memory-error. The common trick is to preallocate a bulk of memory, then free it when you throw the out of memory exception so that you can unwind. When destroying the out-of-memory-object you need to reallocate the bulk of memory.
I know of several cases where this trick was used and it turned out horribly wrong. OOE is NOT recoverable. It may be in some cases, and you can use trick to make them recoverable in more cases, like the one mentioned, but ultimately, you have no guarantee, and worse, no way to know if you are in a recoverable situation or not. The only valid use case i know of to catch this kind of error is at top level to return various error code. Even logging may be broken at this point.
Oct 05 2014
parent "Ola Fosheim Grostad" <ola.fosheim.grostad+dlang gmail.com> writes:
On Monday, 6 October 2014 at 00:29:20 UTC, deadalnix wrote:
 I know of several cases where this trick was used and it turned 
 out horribly wrong. OOE is NOT recoverable. It may be in some 
 cases, and you can use trick to make them recoverable in more 
 cases, like the one mentioned, but ultimately, you have no 
 guarantee, and worse, no way to know if you are in a 
 recoverable situation or not.
You can throw a fatal error if you run out of memory twice. You have to write code that take low memory conditions into account throughout. The problem is not that it is impossible to recover, the problem is that virtual memory have made programmers sloppy.
Oct 05 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 5 October 2014 at 15:03:08 UTC, ketmar via 
Digitalmars-d wrote:
 On Sun, 05 Oct 2014 14:53:37 +0000
 monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 Promises hold provided the precondition your program is in a 
 valid state. Having an Error invalidates that precondition, 
 hence voids that promise.
so Error should not be catchable and should crash immidiately, without any unwinding.
Don't put words in my mouth. Also, Errors do only partial stack unwinding, so yes, once an Error has been thrown, your program should terminate.
 as long as Errors are just another kind of exception,
 the promise must be kept.
Errors aren't Exceptions. They make no promises.
Oct 05 2014
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sun, 05 Oct 2014 16:33:48 +0000
monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Errors aren't Exceptions. They make no promises.
if it looks like a duck, if it quacks like a duck, if it can be catched like a duck... it's a duck. that's not me who titled exception base class Throwable. it can be catched? it is using 'throw'? it does unwinding? it is an exception. and what means 'partial stack unwinding'? by random, or only even stack frames?
Oct 05 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 5 October 2014 at 16:42:24 UTC, ketmar via 
Digitalmars-d wrote:
 it does
 unwinding?
It is not guaranteed by spec (I guess this was added to allow assert(0) to be converted into HLT instruction) though in most cases it does. Neither it is guaranteed to run destructors of RAII entities (and it doesn't already for some cases). Pretty much only reason `Error` is not equivalent to plain `abort` call is to allow some last resort debbugging dump and provide more meaningful information about the failure. Any application that tries to recover from Error in any way falls into unstandard D domain.
Oct 05 2014
parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sun, 05 Oct 2014 16:47:26 +0000
Dicebot via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Pretty much only reason `Error` is not equivalent to plain=20
 `abort` call is to allow some last resort debbugging dump and=20
 provide more meaningful information about the failure.
than it was done very wrong. it's ok to have some arcane chain of "error handlers" in runtime, 'cause writing such handlers is not the kind of task people do often. but allowing to throw Error as any other exception or to catch Error the same way other exceptions can be catched is misleading. any sane person will think about Error as just another kind of Exception, just with different naming. there must be separate case for Errors, something like "final throw", which will not do ANY unwinding, cannot be catched, and just calling "error handlers chain" and aborts. it's not enough to just paint a duck.
Oct 05 2014
prev sibling parent reply Shammah Chancellor <email domain.com> writes:
On 2014-10-05 11:28:59 +0000, monarch_dodra said:

 On Saturday, 4 October 2014 at 18:42:05 UTC, Shammah Chancellor wrote:
 Didn't miss anything.  I was responding to Andrei such that he might 
 think it's not so straightforward to evaluate that code.
 I am with you on this.  It was my original complaint months ago that 
 resulted in this being disallowed behavior.  Specifically because you 
 could stop error propigation by accident even though you did not intend 
 to prevent their propigation.  e.g:
 
 int main()
 {
 	scope(exit) return 0;
 	assert(false, "whoops!");
 }
 
 -S
Isn't this the "should scope(exit/failure) catch Error" issue though? In theory, you should seldom ever catch Errors. I don't understand why "scope(exit)" are catching them.
It doesn't "catch" the error. Propigation should continue as normal. However, in the case I gave a return statement is executed in a cleanup block before propigation can continue. As has been pointed out, this is just like a finally{} block and it behaves the same way. Throws, and returns should be prohibited from those as well.
Oct 05 2014
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 6 October 2014 at 02:35:52 UTC, Shammah Chancellor 
wrote:
 It doesn't "catch" the error. Propigation should continue as 
 normal.
Right, it only "intercepts, cleanups, and rethrows". But the argument is that even that shouldn't happen, as you aren't sure the cleanup code is still relevant. At least, I don't think it should be doing cleanup unless you go out of your way to say: "do this, *even* in case of errors". I mean, your RAII has already failed anyways. Your memory has leaked, your ref counts are of the counter, your transactions are open, your file handles are open... The only thing you should be doing is trying to die gracefully, and maybe salvage user data. Your program is in *ERROR*. Cleanup really shouldn't be the priority, especially if it can potentially add more corruption to your state.
Oct 06 2014
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 10/4/14 2:45 PM, Shammah Chancellor wrote:

 int main()
 {
      scope(exit) return 0;
      assert(false, "whoops!");
 }
The above smells to me like it should be invalid. Specifically, the scope(exit) line by itself. If you want to catch and not propagate an error, you need to use try/catch directly. scope(exit|success|failure) is for cleaning up resources, not returning from the function. -Steve
Oct 06 2014
prev sibling parent reply "David Nadlinger" <code klickverbot.at> writes:
On Friday, 3 October 2014 at 17:50:29 UTC, Andrei Alexandrescu 
wrote:
 On 10/2/14, 8:23 PM, Ali Çehreli wrote:
 "A scope(exit) or scope(success) statement may not exit with a 
 throw,
 goto, break, continue, or return; nor may it be entered with a 
 goto."
Seems to me all these restrictions should be lifted. -- Andrei
Unless we have very good reason, the same restrictions as for finally blocks (i.e. the actual lowering) should apply. David
Oct 03 2014
parent Shammah Chancellor <email domain.com> writes:
On 2014-10-03 20:18:44 +0000, David Nadlinger said:

 On Friday, 3 October 2014 at 17:50:29 UTC, Andrei Alexandrescu wrote:
 On 10/2/14, 8:23 PM, Ali ehreli wrote:
 "A scope(exit) or scope(success) statement may not exit with a throw,
 goto, break, continue, or return; nor may it be entered with a goto."
Seems to me all these restrictions should be lifted. -- Andrei
Unless we have very good reason, the same restrictions as for finally blocks (i.e. the actual lowering) should apply. David
They do.
Oct 03 2014