Discussion:
scope() statements and return
Shammah Chancellor via Digitalmars-d
2014-10-03 02:17:35 UTC
Permalink
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
Ali Çehreli via Digitalmars-d
2014-10-03 03:23:24 UTC
Permalink
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
Shammah Chancellor via Digitalmars-d
2014-10-03 04:09:23 UTC
Permalink
Post by Ali Çehreli via Digitalmars-d
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.
deadalnix via Digitalmars-d
2014-10-03 04:40:53 UTC
Permalink
Post by Ali Çehreli via Digitalmars-d
Post by Shammah Chancellor via Digitalmars-d
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
"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.
ketmar via Digitalmars-d
2014-10-03 04:52:13 UTC
Permalink
On Fri, 03 Oct 2014 04:40:53 +0000
Post by deadalnix via Digitalmars-d
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?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141003/f8e0ff0b/attachment.sig>
Jakob Ovrum via Digitalmars-d
2014-10-03 12:24:11 UTC
Permalink
On Friday, 3 October 2014 at 04:52:24 UTC, ketmar via
Post by ketmar via Digitalmars-d
On Fri, 03 Oct 2014 04:40:53 +0000
Post by deadalnix via Digitalmars-d
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.
Andrei Alexandrescu via Digitalmars-d
2014-10-03 17:50:39 UTC
Permalink
Post by Ali Çehreli via Digitalmars-d
"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
H. S. Teoh via Digitalmars-d
2014-10-03 18:18:58 UTC
Permalink
Post by Andrei Alexandrescu via Digitalmars-d
Post by Ali Çehreli via Digitalmars-d
"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
--
БерегО платье сМПву, а зЎПрПвье сЌПлПЎу.
Andrei Alexandrescu via Digitalmars-d
2014-10-03 19:35:31 UTC
Permalink
Post by H. S. Teoh via Digitalmars-d
Post by Andrei Alexandrescu via Digitalmars-d
Post by Ali Çehreli via Digitalmars-d
"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
int func() {
scope(exit)
return 1;
return 0;
}
What does func() return?
1
Post by H. S. Teoh via Digitalmars-d
int func() {
scope(exit)
return 1;
scope(exit)
return 2;
return 0;
}
2
Post by H. S. Teoh via Digitalmars-d
// What does this function do? What *should* it do??
int func() {
scope(success)
throw new Exception("");
scope(failure)
return 1;
return 0;
}
1
Post by H. S. Teoh via Digitalmars-d
int func() {
hahaha: scope(exit) goto hahaha;
return 1;
}
infinite loop
Post by H. S. Teoh via Digitalmars-d
int func() {
foreach (i; 0..10) {
scope(exit) break;
scope(exit) continue;
return i; // hahahahahaha
}
return i;
}
compile error
Post by H. S. Teoh via Digitalmars-d
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
deadalnix via Digitalmars-d
2014-10-04 03:01:14 UTC
Permalink
On Friday, 3 October 2014 at 19:35:21 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
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).
ketmar via Digitalmars-d
2014-10-04 03:21:13 UTC
Permalink
On Sat, 04 Oct 2014 03:01:14 +0000
Post by deadalnix via Digitalmars-d
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/530edd83/attachment.sig>
Ola Fosheim Grostad via Digitalmars-d
2014-10-04 03:46:35 UTC
Permalink
On Saturday, 4 October 2014 at 03:21:23 UTC, ketmar via
Post by ketmar via Digitalmars-d
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. :-)
ketmar via Digitalmars-d
2014-10-04 04:28:56 UTC
Permalink
On Sat, 04 Oct 2014 03:46:35 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
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."

if some badly designed API does that -- write a wrapper.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/672f41bb/attachment.sig>
Ola Fosheim Grostad via Digitalmars-d
2014-10-04 04:54:38 UTC
Permalink
On Saturday, 4 October 2014 at 04:29:06 UTC, ketmar via
Post by ketmar via Digitalmars-d
Post by Ola Fosheim Grostad via Digitalmars-d
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.
Post by ketmar via Digitalmars-d
if some badly designed API does that -- write a wrapper.
So you need semantic analysis to ensure nothrow.
ketmar via Digitalmars-d
2014-10-04 05:04:50 UTC
Permalink
On Sat, 04 Oct 2014 04:54:38 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
Should or should not, you have to make do with what you get from
libraries.
wrapper is the answer.
Post by Ola Fosheim Grostad via Digitalmars-d
Network being temporarily unavailable is a good reason
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.
Post by Ola Fosheim Grostad via Digitalmars-d
So you need semantic analysis to ensure nothrow.
we have it, and we have that nice "nothrow" attribute.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/b601ba58/attachment.sig>
Ola Fosheim Grostad via Digitalmars-d
2014-10-04 05:22:10 UTC
Permalink
On Saturday, 4 October 2014 at 05:05:00 UTC, ketmar via
Post by ketmar via Digitalmars-d
On Sat, 04 Oct 2014 04:54:38 +0000
Ola Fosheim Grostad via Digitalmars-d
<digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
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).
ketmar via Digitalmars-d
2014-10-04 05:33:13 UTC
Permalink
On Sat, 04 Oct 2014 05:22:10 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
Post by ketmar via Digitalmars-d
Post by Ola Fosheim Grostad via Digitalmars-d
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).
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).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/c03d50c3/attachment.sig>
Ola Fosheim Grostad via Digitalmars-d
2014-10-04 05:37:14 UTC
Permalink
On Saturday, 4 October 2014 at 05:33:29 UTC, ketmar via
Post by ketmar via Digitalmars-d
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,
ketmar via Digitalmars-d
2014-10-04 05:54:06 UTC
Permalink
On Sat, 04 Oct 2014 05:37:14 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/a87f2347/attachment.sig>
Ola Fosheim Grostad via Digitalmars-d
2014-10-04 05:58:47 UTC
Permalink
On Saturday, 4 October 2014 at 05:54:20 UTC, ketmar via
Digitalmars-d wrote:,
Post by ketmar via Digitalmars-d
'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.
Post by ketmar via Digitalmars-d
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.
ketmar via Digitalmars-d
2014-10-04 06:28:43 UTC
Permalink
On Sat, 04 Oct 2014 05:58:47 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
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! ;-)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/a400005b/attachment.sig>
via Digitalmars-d
2014-10-04 07:29:57 UTC
Permalink
On Saturday, 4 October 2014 at 06:28:52 UTC, ketmar via
Post by ketmar via Digitalmars-d
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. :-)
Andrei Alexandrescu via Digitalmars-d
2014-10-04 21:48:26 UTC
Permalink
Post by ketmar via Digitalmars-d
On Sat, 04 Oct 2014 05:58:47 +0000
Ola Fosheim Grostad via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Ola Fosheim Grostad via Digitalmars-d
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
ketmar via Digitalmars-d
2014-10-05 06:01:26 UTC
Permalink
On Sat, 04 Oct 2014 14:48:26 -0700
Andrei Alexandrescu via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Andrei Alexandrescu via Digitalmars-d
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141005/01da356f/attachment.sig>
Timon Gehr via Digitalmars-d
2014-10-07 12:59:52 UTC
Permalink
Post by ketmar via Digitalmars-d
On Sat, 04 Oct 2014 14:48:26 -0700
Andrei Alexandrescu via Digitalmars-d <digitalmars-d at puremagic.com>
Post by Andrei Alexandrescu via Digitalmars-d
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);
ketmar via Digitalmars-d
2014-10-07 13:57:46 UTC
Permalink
On Tue, 07 Oct 2014 14:59:52 +0200
Post by Timon Gehr via Digitalmars-d
What's the point anyway?
non-final try/catch will not make function "nothrow".
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141007/ebf5f2c6/attachment.sig>
Timon Gehr via Digitalmars-d
2014-10-07 14:08:33 UTC
Permalink
Post by ketmar via Digitalmars-d
On Tue, 07 Oct 2014 14:59:52 +0200
Post by Timon Gehr via Digitalmars-d
What's the point anyway?
non-final try/catch will not make function "nothrow".
void doStuff(){ }

void main() nothrow{
try{ doStuff(); }
catch assert(0);
}
ketmar via Digitalmars-d
2014-10-07 14:23:33 UTC
Permalink
On Tue, 07 Oct 2014 16:08:33 +0200
Post by ketmar via Digitalmars-d
Post by Timon Gehr via Digitalmars-d
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141007/87c3f717/attachment.sig>
Timon Gehr via Digitalmars-d
2014-10-07 14:34:12 UTC
Permalink
Post by ketmar via Digitalmars-d
On Tue, 07 Oct 2014 16:08:33 +0200
Post by ketmar via Digitalmars-d
Post by Timon Gehr via Digitalmars-d
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
Post by ketmar via Digitalmars-d
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?
Post by ketmar via Digitalmars-d
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); }
}
ketmar via Digitalmars-d
2014-10-07 15:01:30 UTC
Permalink
On Tue, 07 Oct 2014 16:34:12 +0200
Post by Timon Gehr via Digitalmars-d
import core.exception;
void doStuff(){ }
void main() nothrow{
try{ doStuff(); }
catch(UnicodeException){ }
}
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.
Post by Timon Gehr via Digitalmars-d
Post by ketmar via Digitalmars-d
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.
Post by Timon Gehr via Digitalmars-d
Post by ketmar via Digitalmars-d
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); }
}
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141007/25db97b7/attachment-0001.sig>
Andrei Alexandrescu via Digitalmars-d
2014-10-04 03:47:21 UTC
Permalink
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
deadalnix via Digitalmars-d
2014-10-04 04:47:44 UTC
Permalink
On Saturday, 4 October 2014 at 03:21:23 UTC, ketmar via
Post by ketmar via Digitalmars-d
On Sat, 04 Oct 2014 03:01:14 +0000
Post by deadalnix via Digitalmars-d
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
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.
Ola Fosheim Grostad via Digitalmars-d
2014-10-04 05:05:27 UTC
Permalink
Post by deadalnix via Digitalmars-d
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?
ketmar via Digitalmars-d
2014-10-04 05:13:40 UTC
Permalink
On Sat, 04 Oct 2014 04:47:44 +0000
Post by deadalnix via Digitalmars-d
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141004/82df60ea/attachment.sig>
Andrei Alexandrescu via Digitalmars-d
2014-10-04 21:44:43 UTC
Permalink
Post by Andrei Alexandrescu via Digitalmars-d
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
Shammah Chancellor via Digitalmars-d
2014-10-04 23:51:43 UTC
Permalink
Post by Andrei Alexandrescu via Digitalmars-d
Post by Andrei Alexandrescu via Digitalmars-d
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
Shammah Chancellor via Digitalmars-d
2014-10-04 05:08:38 UTC
Permalink
Post by H. S. Teoh via Digitalmars-d
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;
}
}
Post by H. S. Teoh via Digitalmars-d
// 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
H. S. Teoh via Digitalmars-d
2014-10-04 06:09:39 UTC
Permalink
[...]
Post by Shammah Chancellor via Digitalmars-d
Post by H. S. Teoh via Digitalmars-d
// 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
--
МалеМькОе ЎеткО - ЌалеМькОе беЎкО.
Shammah Chancellor via Digitalmars-d
2014-10-04 18:45:47 UTC
Permalink
On Sat, Oct 04, 2014 at 01:08:38AM -0400, Shammah Chancellor via
[...]
Post by Shammah Chancellor via Digitalmars-d
Post by H. S. Teoh via Digitalmars-d
// 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
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
monarch_dodra via Digitalmars-d
2014-10-05 11:28:59 UTC
Permalink
On Saturday, 4 October 2014 at 18:42:05 UTC, Shammah Chancellor
Post by Shammah Chancellor via Digitalmars-d
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
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.
ketmar via Digitalmars-d
2014-10-05 12:36:18 UTC
Permalink
On Sun, 05 Oct 2014 11:28:59 +0000
Post by monarch_dodra via Digitalmars-d
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?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141005/224dde76/attachment.sig>
monarch_dodra via Digitalmars-d
2014-10-05 14:53:37 UTC
Permalink
On Sunday, 5 October 2014 at 12:36:30 UTC, ketmar via
Post by ketmar via Digitalmars-d
On Sun, 05 Oct 2014 11:28:59 +0000
monarch_dodra via Digitalmars-d <digitalmars-d at puremagic.com>
Post by monarch_dodra via Digitalmars-d
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.
ketmar via Digitalmars-d
2014-10-05 15:02:56 UTC
Permalink
On Sun, 05 Oct 2014 14:53:37 +0000
Post by monarch_dodra via Digitalmars-d
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. as long as Errors are just another kind of exception,
the promise must be kept.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141005/9670a07e/attachment-0001.sig>
via Digitalmars-d
2014-10-05 16:30:46 UTC
Permalink
On Sunday, 5 October 2014 at 15:03:08 UTC, ketmar via
Post by ketmar via Digitalmars-d
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.
Dicebot via Digitalmars-d
2014-10-05 16:42:36 UTC
Permalink
On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim GrÞstad
Post by via Digitalmars-d
Does D have exception chaining?
Yes. http://dlang.org/phobos/object.html#.Throwable.next
Though it seems to do more harm then good so far.
Andrei Alexandrescu via Digitalmars-d
2014-10-05 17:03:22 UTC
Permalink
Post by Dicebot via Digitalmars-d
Post by via Digitalmars-d
Does D have exception chaining?
Yes. http://dlang.org/phobos/object.html#.Throwable.next
Though it seems to do more harm then good so far.
What harm does it do? -- Andrei
Dicebot via Digitalmars-d
2014-10-05 17:09:14 UTC
Permalink
On Sunday, 5 October 2014 at 17:03:07 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Post by Dicebot via Digitalmars-d
Post by via Digitalmars-d
Does D have exception chaining?
Yes. http://dlang.org/phobos/object.html#.Throwable.next
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.
Walter Bright via Digitalmars-d
2014-10-06 07:27:58 UTC
Permalink
Post by Andrei Alexandrescu via Digitalmars-d
Post by Dicebot via Digitalmars-d
Post by via Digitalmars-d
Does D have exception chaining?
Yes. http://dlang.org/phobos/object.html#.Throwable.next
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.
via Digitalmars-d
2014-10-06 11:32:53 UTC
Permalink
Post by Walter Bright via Digitalmars-d
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. :-/
Andrei Alexandrescu via Digitalmars-d
2014-10-06 13:48:23 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Post by Andrei Alexandrescu via Digitalmars-d
Post by Dicebot via Digitalmars-d
Post by via Digitalmars-d
Does D have exception chaining?
Yes. http://dlang.org/phobos/object.html#.Throwable.next
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
monarch_dodra via Digitalmars-d
2014-10-06 14:24:00 UTC
Permalink
On Monday, 6 October 2014 at 13:48:07 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Post by Dicebot via Digitalmars-d
On Sunday, 5 October 2014 at 17:03:07 UTC, Andrei
Post by Andrei Alexandrescu via Digitalmars-d
Post by Dicebot via Digitalmars-d
On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim
Post by via Digitalmars-d
Does D have exception chaining?
Yes. http://dlang.org/phobos/object.html#.Throwable.next
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.
Andrei Alexandrescu via Digitalmars-d
2014-10-06 14:54:37 UTC
Permalink
If your "catch" throws an exception, then the new exception simply
//----
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
monarch_dodra via Digitalmars-d
2014-10-06 16:55:38 UTC
Permalink
On Monday, 6 October 2014 at 14:54:21 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Post by monarch_dodra via Digitalmars-d
If your "catch" throws an exception, then the new exception
simply
//----
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?
Andrei Alexandrescu via Digitalmars-d
2014-10-06 16:59:51 UTC
Permalink
Post by Andrei Alexandrescu via Digitalmars-d
If your "catch" throws an exception, then the new exception simply
//----
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
monarch_dodra via Digitalmars-d
2014-10-07 07:36:54 UTC
Permalink
On Monday, 6 October 2014 at 16:59:35 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Whenever an exception is converted to a string, the chained
exceptions should be part of it too.
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?
via Digitalmars-d
2014-10-07 10:56:18 UTC
Permalink
"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.
Andrei Alexandrescu via Digitalmars-d
2014-10-07 13:39:06 UTC
Permalink
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
Regan Heath via Digitalmars-d
2014-10-08 13:39:45 UTC
Permalink
On Tue, 07 Oct 2014 14:39:06 +0100, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
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
I have a couple of examples here in front of me. This is in C#...

[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/
Jakob Ovrum via Digitalmars-d
2014-10-06 17:11:58 UTC
Permalink
Post by monarch_dodra via Digitalmars-d
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.
deadalnix via Digitalmars-d
2014-10-07 02:26:17 UTC
Permalink
Post by Jakob Ovrum via Digitalmars-d
Post by monarch_dodra via Digitalmars-d
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
---
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.
deadalnix via Digitalmars-d
2014-10-07 02:25:30 UTC
Permalink
On Monday, 6 October 2014 at 13:48:07 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
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.
Andrei Alexandrescu via Digitalmars-d
2014-10-07 03:19:05 UTC
Permalink
Post by monarch_dodra via Digitalmars-d
On Monday, 6 October 2014 at 13:48:07 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
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
deadalnix via Digitalmars-d
2014-10-07 07:07:46 UTC
Permalink
On Tuesday, 7 October 2014 at 03:19:06 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Post by deadalnix via Digitalmars-d
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.
via Digitalmars-d
2014-10-05 17:15:11 UTC
Permalink
Post by Dicebot via Digitalmars-d
Yes. http://dlang.org/phobos/object.html#.Throwable.next
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.
deadalnix via Digitalmars-d
2014-10-06 00:29:18 UTC
Permalink
On Sunday, 5 October 2014 at 16:30:47 UTC, Ola Fosheim GrÞstad
Post by via Digitalmars-d
On Sunday, 5 October 2014 at 15:03:08 UTC, ketmar via
Post by ketmar via Digitalmars-d
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.
Ola Fosheim Grostad via Digitalmars-d
2014-10-06 06:06:34 UTC
Permalink
Post by deadalnix via Digitalmars-d
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.
monarch_dodra via Digitalmars-d
2014-10-05 16:33:48 UTC
Permalink
On Sunday, 5 October 2014 at 15:03:08 UTC, ketmar via
Post by ketmar via Digitalmars-d
On Sun, 05 Oct 2014 14:53:37 +0000
monarch_dodra via Digitalmars-d <digitalmars-d at puremagic.com>
Post by monarch_dodra via Digitalmars-d
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.
Post by ketmar via Digitalmars-d
as long as Errors are just another kind of exception,
the promise must be kept.
Errors aren't Exceptions. They make no promises.
ketmar via Digitalmars-d
2014-10-05 16:42:13 UTC
Permalink
On Sun, 05 Oct 2014 16:33:48 +0000
Post by monarch_dodra via Digitalmars-d
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?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141005/3a000914/attachment.sig>
Dicebot via Digitalmars-d
2014-10-05 16:47:26 UTC
Permalink
On Sunday, 5 October 2014 at 16:42:24 UTC, ketmar via
Post by ketmar via Digitalmars-d
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.
ketmar via Digitalmars-d
2014-10-05 17:00:05 UTC
Permalink
On Sun, 05 Oct 2014 16:47:26 +0000
Post by Dicebot via Digitalmars-d
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.
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141005/f01ffe9b/attachment-0001.sig>
Shammah Chancellor via Digitalmars-d
2014-10-06 02:39:36 UTC
Permalink
Post by Shammah Chancellor via Digitalmars-d
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
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.
monarch_dodra via Digitalmars-d
2014-10-06 07:15:25 UTC
Permalink
On Monday, 6 October 2014 at 02:35:52 UTC, Shammah Chancellor
Post by Shammah Chancellor via Digitalmars-d
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.
Steven Schveighoffer via Digitalmars-d
2014-10-06 14:54:33 UTC
Permalink
Post by Shammah Chancellor via Digitalmars-d
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
David Nadlinger via Digitalmars-d
2014-10-03 20:18:44 UTC
Permalink
On Friday, 3 October 2014 at 17:50:29 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Post by Ali Çehreli via Digitalmars-d
"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
Shammah Chancellor via Digitalmars-d
2014-10-04 05:04:37 UTC
Permalink
Post by Andrei Alexandrescu via Digitalmars-d
Post by Ali Çehreli via Digitalmars-d
"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.
Loading...