March 01, 2006
In article <dtsgcf$1i3q$1@digitaldaemon.com>, Hasan Aljudy says...
>
>Thomas Kuehne wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>> 
>> bobef schrieb am 2006-02-26:
>> 
>>>Knud S�rensen wrote:
>>>
>>>
>>>>Freshmeat is the slashdot equivalent for software.
>>>
>>>Forgive my ignorance, but what is slashdot?
>> 
>> 
>> http://slashdot.org
>> 
>> Thomas
>> 
>> 
>> -----BEGIN PGP SIGNATURE-----
>> 
>> iD8DBQFEAX4/3w+/yD4P9tIRAjvuAJwPvtROSVZvxhiVZkzrJK+5zq2hDQCeI3Bt
>> ThkzHvadOtJAdWlCXR6c6zc=
>> =sWOz
>> -----END PGP SIGNATURE-----
>
>Still, what is it? I've been there before .. didn't quite get it. Why is it so popular?!

It's technology and scientific news and covers a lot of 'nerd' interest stuff; it's highly configurable if you have an account.

Every article has free-form user comments and discussion, which means you not only see the news article, but can pick up dozens of links to related info, get opinions on both sides, etc.  (Many of the participants are highly uninformed, but that is hard to avoid on the web...)

It's news, discussion, conversation, and a sort of "commonwealth" community, and each discussion is anchored off of a "real" news article, book review, or writeup, usually somewhere else.  In this way its like a mixture of newsgroup discussions, journalism, and wiki-like community authoring.

Like almost all human communities, the appeal is determined mostly by the types of people that exist there (i.e. prisons versus country clubs versus rock concerts).  So its probably very grating if you don't like techie/trekkie/IT types.

[But it's starting to look commonplace now because everyone copied them.  Every revolution is unthinkable beforehand and obvious afterwards...]

Kevin


March 01, 2006
Walter Bright wrote:
> I hope that these buggy examples show just how hard it is to get try-catch-finally to be correct, and how easy it is to get the on_scope correct. This leads me to believe that try-catch-finally is just conceptually wrong, as it does not match up with how we think despite being in common use for over a decade. 

This is very interesting. Seems to me that these on_scope_xxx are kind of "naked destructors". If you consider them to be the low-level construct, then putting a destructor into a class means: when the constructor is called, insert "on_scope_exit ~this()" at the same time.

Is the convoluted nature of the RAII solution simply because
the same destructor is executed regardless of whether the function was exited normally, or whether an exception occurred? And because there's no easy way of determining if you are inside an exception handler. So you only have "finally", without "catch".
I wonder if destructors could be jazzed up, so that they can insert an "on_scope_failure" as well as "on_scope_exit"?
Maybe called ~catch()?

class Foo
{
~catch() {
unwind_foo();
}
}

class Bar
{
  ~this() { // destroy bar
   }
  ~catch() {
   unwind_bar();
  //  now we go to ~this(), which behaves like finally.
  }
}

Transaction abc()
{
    Foo f;
    Bar b;
    Def d;

    f = dofoo();
    b = dobar();
    d = dodef();

    return Transaction(f, b, d);
}

Doesn't have the flexibility of on_scope, where you have access to all variables -- but on the other hand, it has the RAII benefit that users of the class don't need to remember to do it.

Just an idea.
March 01, 2006
Don Clugston wrote:
<snip>
> Is the convoluted nature of the RAII solution simply because
> the same destructor is executed regardless of whether the function was exited normally, or whether an exception occurred? And because there's no easy way of determining if you are inside an exception handler. So you only have "finally", without "catch".
> I wonder if destructors could be jazzed up, so that they can insert an "on_scope_failure" as well as "on_scope_exit"?
> Maybe called ~catch()?
<snip>

Can you think of a practical use for this idea?  I'm not sure what sense it would make, considering that the class knows nothing of what the code that failed was doing at the time.

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:- C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on the 'group where everyone may benefit.
March 01, 2006
"Andrew Fedoniouk" <news@terrainformatica.com> wrote in message news:du2q1c$4tv$1@digitaldaemon.com...
>
> "Walter Bright" <newshound@digitalmars.com> wrote in message
>> The new bug in the above code is that the catch block fails to rethrow o.
> Let's say it was an intention. Pretty common by the way.

Perhaps, but the stated point of the example was to show equivalent try-catch code to the on_scope example. It isn't equivalent.

> Well try first to explain what will happen on
> on_scope_success { delete baz; throw foo; }
> on_scope_exit { delete baz; throw foo; }
>
> What "lexical order" will be used here? What scope guards will be invoked and so on.

Throwing from inside an on_scope statement is as bad an idea as throwing inside a destructor or inside a finally block. Doing it in an on_scope_exit or on_scope_failure will result in a double-fault exception. Doing it in an on_scope_success will be like throwing at the } of a scope.

> Having on_scope_*** spread all other the "... lots of code ..."  will
> create
> code maintainance nightmare as to trace visually what will happen and when
> will not be a task for human anymore.

I submit that based on what's been posted in this thread, it's easier to get on_scope *correct* than try-finally, because most of the try-finally examples posted here do not work as intended by the author. Not only that, the try-finally examples fail in ways that are difficult to write test cases for, so the errors are likely to go unnoticed.

> And as far as I understand main idea of on_scope_exit is a sort of poor
> man struct destructor...
> I suspect that you are thinking about how to remove 'auto'/RAII, right?

No. RAII is for managing resources, which is different from managing state or transactions. try-catch is still needed, as on_scope doesn't catch exceptions. It's try-finally that becomes redundant, though it is useful to keep it because so many people are used to it.


March 01, 2006
"S. Chancellor" <dnewsgr@mephit.kicks-ass.org> wrote in message news:du376e$1fbf$2@digitaldaemon.com...
> Something like this would be equivalent?
>
> Transaction abc()
> {
> Foo f;
>     Bar b;
>     Def d;
> Auto scoped = new Scoper();  //scoped.exit() can be called by the
> destructor.  We won't add a finally block.
>
> try {
> scoped.failures ~= void delegate () { dofoo_unwind(f); }
>     f = dofoo();
>
> scoped.failures ~= void delegate () { dobar_unwind(b); }
> b = dobar();
>
> scoped.success()
> } catch (Exception o) {
> scoped.failed()
> throw o;
> }
>
> return Transaction(f, b, d);
> }

Should be:
     f = dofoo();
     scoped.failures ~= void delegate () { dofoo_unwind(f); }
etc. Other than that, it looks like it'll work, but it's a lot more code
than on_scope. You also need to be sure that the delegates don't refer to
any variables declared inside the try block, as those variables no longer
exist in the catch block - and the compiler can't catch that error. This
isn't a problem with on_scope.


March 01, 2006
Walter Bright wrote:
> "Andrew Fedoniouk" <news@terrainformatica.com> wrote in message news:du2q1c$4tv$1@digitaldaemon.com...
>> "Walter Bright" <newshound@digitalmars.com> wrote in message
>>> The new bug in the above code is that the catch block fails to rethrow o.
>> Let's say it was an intention. Pretty common by the way.
> 
> Perhaps, but the stated point of the example was to show equivalent try-catch code to the on_scope example. It isn't equivalent.

That may have been the point of the original example, but it wasn't the point of mine.  But it's water under the bridge, as you answered my question either way :-)

>> Having on_scope_*** spread all other the "... lots of code ..."  will create
>> code maintainance nightmare as to trace visually what will happen and when will not be a task for human anymore.
> 
> I submit that based on what's been posted in this thread, it's easier to get on_scope *correct* than try-finally, because most of the try-finally examples posted here do not work as intended by the author. Not only that, the try-finally examples fail in ways that are difficult to write test cases for, so the errors are likely to go unnoticed.

The only complaint I've heard about on_scope that I consider valid is that program flow may be a tad confusing in excessively long functions.  But traditional RAII is no better, and try-finally introduces maintenance and readability problems by breaking the logical connection between unwinding code and the code block it's associated with.  It's also helpful that throwing an exception while another is in-flight in D does not result in program termination, even if doing so is not advisable.

>> And as far as I understand main idea of on_scope_exit is a sort of poor man struct destructor...
>> I suspect that you are thinking about how to remove 'auto'/RAII, right?
> 
> No. RAII is for managing resources, which is different from managing state or transactions. try-catch is still needed, as on_scope doesn't catch exceptions. It's try-finally that becomes redundant, though it is useful to keep it because so many people are used to it. 

That may have been the original intent, but RAII has since become almost indispensable for writing exception-safe code, be it with resources, transactions, or something else.  Personally, I've never liked try-finally, but I attribute that to my C++ background.  If I were a Java person it may be a different story.


Sean
March 01, 2006
Don Clugston wrote:
> Walter Bright wrote:
>> I hope that these buggy examples show just how hard it is to get try-catch-finally to be correct, and how easy it is to get the on_scope correct. This leads me to believe that try-catch-finally is just conceptually wrong, as it does not match up with how we think despite being in common use for over a decade. 
> 
> This is very interesting. Seems to me that these on_scope_xxx are kind of "naked destructors". If you consider them to be the low-level construct, then putting a destructor into a class means: when the constructor is called, insert "on_scope_exit ~this()" at the same time.

on_scope does practically eliminate the need for an 'auto' keyword, assuming auto classes would be allocated on the heap either way.

> Is the convoluted nature of the RAII solution simply because
> the same destructor is executed regardless of whether the function was exited normally, or whether an exception occurred? And because there's no easy way of determining if you are inside an exception handler. So you only have "finally", without "catch".
> I wonder if destructors could be jazzed up, so that they can insert an "on_scope_failure" as well as "on_scope_exit"?

I've considered adding functionality to Ares to allow a user to determine if an exception is currently in flight--C++ offers this but it's little used as it's not terribly reliable.  But with on_scope there seems little need for this.

> Maybe called ~catch()?
> 
> class Foo
> {
> ~catch() {
> unwind_foo();
> }
> }
> 
> class Bar
> {
>   ~this() { // destroy bar
>    }
>   ~catch() {
>    unwind_bar();
>   //  now we go to ~this(), which behaves like finally.
>   }
> }
> 
> Transaction abc()
> {
>     Foo f;
>     Bar b;
>     Def d;
> 
>     f = dofoo();
>     b = dobar();
>     d = dodef();
> 
>     return Transaction(f, b, d);
> }
> 
> Doesn't have the flexibility of on_scope, where you have access to all variables -- but on the other hand, it has the RAII benefit that users of the class don't need to remember to do it.

True.  But I would argue that the burden of writing exception-safe code is on the function writer moreso than the class writer, largely because the class writer can't predict or address every way that his class may be used.  on_scope also allows a bit more flexibility:

{
    Foo f = acquireFoo();

    on_scope_exit    f.commitAll();
    on_scope_failure f.unwindAll();

    f.setFirst();
    {
        f.setSecond();

        on_scope_failure f.unwindLast();
    }
}


Sean
March 01, 2006
Sean Kelly wrote:
<snip>
> on_scope does practically eliminate the need for an 'auto' keyword, assuming auto classes would be allocated on the heap either way.
<snip>

How would you declare an auto class without the auto keyword?

Moreover, while

    auto Qwert yuiop = new Qwert;

appears to be syntactic sugar for

    Qwert yuiop = new Qwert;
    on_scope_exit delete yuiop;

the former does still (I assume) have the advantage of stopping you from inadvertently reassigning to yuiop.

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:- C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on the 'group where everyone may benefit.
March 01, 2006
"Sean Kelly" <sean@f4.ca> wrote in message news:du4mfe$18k5$1@digitaldaemon.com...
> Walter Bright wrote:
>> RAII is for managing resources, which is different from managing state or transactions. try-catch is still needed, as on_scope doesn't catch exceptions. It's try-finally that becomes redundant, though it is useful to keep it because so many people are used to it.
>
> That may have been the original intent, but RAII has since become almost indispensable for writing exception-safe code, be it with resources, transactions, or something else.

RAII is used for those other things in C++ because there is *no other choice*. Nevertheless, the reality of using destructors to manage transaction processing is:

1) it's so hard to do that most programmers simply ignore the problem, trusting to luck that exceptions won't happen

2) those that do try it, most of the time get it wrong

3) it's pretty hard to visually inspect the code and determine that it is exception safe

This suggests to me that RAII and try-finally are the wrong paradigms for doing transaction programming. I've attended Scott Meyer's insightful lecture on doing transaction programming in C++. There is no hope for it to be reliably done by anyone but experts.


> Personally, I've never liked try-finally, but I attribute that to my C++ background.  If I were a Java person it may be a different story.

Try-finally and RAII are like goto's. They work, but aren't using whiles, fors, switches, etc., much more natural?


March 01, 2006
"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:du4q5j$1ckc$1@digitaldaemon.com...
> Moreover, while
>
>     auto Qwert yuiop = new Qwert;
>
> appears to be syntactic sugar for
>
>     Qwert yuiop = new Qwert;
>     on_scope_exit delete yuiop;

That's correct. In fact, it's implemented that way <g>.

> the former does still (I assume) have the advantage of stopping you from inadvertently reassigning to yuiop.

Yes, whereas the latter allows state unwinding for things that aren't class objects. Without on_scope_exit, extra dummy classes would have to be defined for each, turning a one liner into a dozen lines that appear out of context.