View mode: basic / threaded / horizontal-split · Log in · Help
February 28, 2006
Re: Negative
"Sean Kelly" <sean@f4.ca> wrote in message 
news:du225a$2549$1@digitaldaemon.com...
>>> But
>>> Transaction abc()
>>> {
>>>    try {
>>>      Foo f = dofoo();
>>>      Bar b = dobar();
>>>      Def d = dodef();
>>>      return Transaction(f, b, d);
>>>   } catch(object er) {
>>>        delete f; delete b; delete d;
>>>   }
>>> }
>>> is not worse to be honest.
>>
>> It is worse because it won't even compile. f, b, and d are not in scope 
>> in the catch statement. Even if they were, there's still a serious bug - 
>> if dofoo() throws an exception, then the catch statement will attempt to 
>> delete b and d, which are not even initialized yet.
>
> Is it really a bug to call delete on a null reference?  This is 
> well-defined behavior in C++.

It's not even a null reference.
February 28, 2006
Re: Negative
Walter Bright wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message 
> news:du225a$2549$1@digitaldaemon.com...
>>>> But
>>>> Transaction abc()
>>>> {
>>>>    try {
>>>>      Foo f = dofoo();
>>>>      Bar b = dobar();
>>>>      Def d = dodef();
>>>>      return Transaction(f, b, d);
>>>>   } catch(object er) {
>>>>        delete f; delete b; delete d;
>>>>   }
>>>> }
>>>> is not worse to be honest.
>>> It is worse because it won't even compile. f, b, and d are not in scope 
>>> in the catch statement. Even if they were, there's still a serious bug - 
>>> if dofoo() throws an exception, then the catch statement will attempt to 
>>> delete b and d, which are not even initialized yet.
>> Is it really a bug to call delete on a null reference?  This is 
>> well-defined behavior in C++.
> 
> It's not even a null reference. 

Not in the above example, but then the above example doesn't even 
compile.  I assumed you were talking about something like this:

Foo f;
Bar b;
try {
    f = dofoo();
    b = dobar();
} catch( Object o ) {
    delete f; delete b;
}

It's quite possible for f and b to both be uninitialized, yet I would 
expect the delete calls to be well-defined anyway.

Sean
February 28, 2006
Re: Negative
"Sean Kelly" <sean@f4.ca> wrote in message 
news:du25eb$288m$3@digitaldaemon.com...
> Not in the above example, but then the above example doesn't even compile. 
> I assumed you were talking about something like this:
>
> Foo f;
> Bar b;
> try {
>     f = dofoo();
>     b = dobar();
> } catch( Object o ) {
>     delete f; delete b;
> }
>
> It's quite possible for f and b to both be uninitialized, yet I would 
> expect the delete calls to be well-defined anyway.

delete is well defined, and works properly with null. For more complex 
unwinding, you'll need to add state variables to keep track of what has been 
set and what hasn't.

The new bug in the above code is that the catch block fails to rethrow o.

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.
February 28, 2006
Re: Negative
Walter Bright wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message 
> news:du25eb$288m$3@digitaldaemon.com...
>> Not in the above example, but then the above example doesn't even compile. 
>> I assumed you were talking about something like this:
>>
>> Foo f;
>> Bar b;
>> try {
>>     f = dofoo();
>>     b = dobar();
>> } catch( Object o ) {
>>     delete f; delete b;
>> }
>>
>> It's quite possible for f and b to both be uninitialized, yet I would 
>> expect the delete calls to be well-defined anyway.
> 
> delete is well defined, and works properly with null. For more complex 
> unwinding, you'll need to add state variables to keep track of what has been 
> set and what hasn't.

That's all I was asking.  I wondered at the implications of:

"there's still a serious bug - if dofoo() throws an exception, then the 
catch statement will attempt to delete b and d, which are not even 
initialized yet"

> The new bug in the above code is that the catch block fails to rethrow o.

Arguably not a bug, as this could be intended behavior.  However, I 
would think it's clear that the above code was merely intended to 
clarify a previous statement.  I wouldn't suggest that it is correct or 
well-written :-)

> 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.

I've been sold on Andrei's method since he first introduced it, so no 
issue there.  It's certainly far simpler and more meaningful than the 
backflips often required by RAII.  And while the proposed C++ shared_ptr 
syntax makes some progress for this purpose, it's still a far cry from 
on_scope_*, particularly when paired with inner functions.


Sean
February 28, 2006
Re: Negative
On Wed, 01 Mar 2006 06:19:35 +1100, Walter Bright  
<newshound@digitalmars.com> 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.

Execellent point, Walter. The concept of scope guards in D is very  
exciting and a real winner in my opinion. I'm looking forward to the  
syntax improving and stabilizing so I can use it in real applications.

And may I be so bold as to paraphase you ...

  : I hope that these buggy examples show just how hard it is to get
  : C-style booleans to be correct, and how easy it is to get the  
semantically
  : boolean correct. This leads me to believe that the C-style boolean is  
just
  : conceptually wrong, as it does not match up with how we think despite
  : being in common use for many decades.

<G><G><G>

-- 
Derek Parnell
Melbourne, Australia
March 01, 2006
Re: Negative
"Walter Bright" <newshound@digitalmars.com> wrote in message 
news:du2925$2cvj$1@digitaldaemon.com...
>
> "Sean Kelly" <sean@f4.ca> wrote in message 
> news:du25eb$288m$3@digitaldaemon.com...
>> Not in the above example, but then the above example doesn't even 
>> compile. I assumed you were talking about something like this:
>>
>> Foo f;
>> Bar b;
>> try {
>>     f = dofoo();
>>     b = dobar();
>> } catch( Object o ) {
>>     delete f; delete b;
>> }
>>
>> It's quite possible for f and b to both be uninitialized, yet I would 
>> expect the delete calls to be well-defined anyway.
>
> delete is well defined, and works properly with null. For more complex 
> unwinding, you'll need to add state variables to keep track of what has 
> been set and what hasn't.
>
> 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.

>
> 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.

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.
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.

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?

Andrew.
http://terrainformatica.com
March 01, 2006
Re: DMD 0.148 - scope guard
Chris Miller wrote:
> On Mon, 27 Feb 2006 17:16:38 -0500, Dawid Ciężarkiewicz  
> <dawid.ciezarkiewicz@gmail.com> wrote:
> 
>> Chris Miller wrote:
>>
>>> This format looks good to me:
>>>
>>> scope(exit)  foo();
>>> scope(success)  bar();
>>> scope(failure)  baz();

This gets my vote too.

And then it would look natural, if you ever need more than one function run:

scope(failure) foo();
scope(success) { bar(); haveAParty(); writeHome(); }
scope(exit) yawn();

>> Yeap. It's nice. Maybe s/success/pass/ s/failure/fail/ would even  
>> improve it
>> a little.
> 
> Good one.

That's kind of neat, too. Having all three alternatives with same number 
of characters, makes it tidy:

scope(exit)  foo();
scope(pass)  bar();
scope(fail)  baz();

Except of course, that "pass" might look like "skip" to somebody new to D.
March 01, 2006
Re: Negative
"Derek Parnell" <derek@psych.ward> wrote in message 
news:op.s5pd12y86b8z09@ginger.vic.bigpond.net.au...
> <G><G><G>

Nice try :-)
March 01, 2006
Re: DMD 0.148 - scope guard
On 2006-02-28 00:08:01 -0800, "Andrew Fedoniouk" 
<news@terrainformatica.com> said:

> 
> "S. Chancellor" <dnewsgr@mephit.kicks-ass.org> wrote in message 
> news:du0lmk$dbg$1@digitaldaemon.com...
>> On 2006-02-25 18:06:36 -0800, "Walter Bright" <newshound@digitalmars.com> said:
>> 
>>> Scope guards are a novel feature no other language has. They're based 
>>> on Andrei Alexandrescu's scope guard macros, which have led to 
>>> considerable interest in the idea. Check out the article 
>>> www.digitalmars.com/d/exception-safe.html
>> 
>> The only thing I see that's amazingly useful about this is the 
>> on_scope_success.  Having a block of code that is only executed when an 
>> exception is NOT thrown would be nice.  However, the rest of this stuff 
>> seems like rocks under the water.  Your example of the new programmer 
>> coming in reads like this to me:  "The new programmer may not take the 
>> time to actually read the code he's modifying, so lets stick hidden 
>> stuff in there to take care of things he might have missed."  Which 
>> doesn't seem very logical to me, as it may be just as important to 
>> modify those on success/on failure blocks and miss them.
>> 
>> I'd say add another option to try..catch..finally paradigm.
>> 
>> -S.
>> 
> 
> try {
> 
>    something horrible here....
> 
>    //on_scope_success:
> 
>    ... and here is on success part
> 
> }
> 
> Why do you need separate 'passed' part?
> 
> Andrew.

You don't.  I wasn't thinking clearly.  I guess I was confused by the 
fact that there was an on_scope_success in this new addition.

-S.
March 01, 2006
Re: try..catch..pass..finally Was: DMD 0.148 - scope guard
On 2006-02-27 23:17:06 -0800, "Regan Heath" <regan@netwin.co.nz> said:

> On Tue, 28 Feb 2006 06:34:00 +0000 (UTC), Tom Johnson  
> <Tom_member@pathlink.com> wrote:
>>> I'd say add another option to try..catch..finally paradigm.
>>> 
>>> -S.
>> 
>> Seconded.  For more fun, next we can debate whether the syntax should be:
>> 
>> 1.  try..pass..catch..finally
>> 2.  try..catch..pass...finally
>> 3.  try..catch..finally..pass
> 
> No, on_scope gives us more than try/catch/finally. Let me try this 
> another  way.
> 
> "catch" from try/catch/finally allows:
>   - you to execute a static/pre-defined set of code in the event that 
> there  is a failure in the current scope.
> 
> "finally" from try/catch/finally allows:
>   - you to execute a static/pre-defined set of code at the exit of the  
> current scope in all cases.
> 
> Compare that to:
> 
> on_scope_failure allows:
>   - you to add one or more sets of code, at the points at which they 
> become  required, to the list of things to execute in the event of a 
> failure.
> 
> on_scope_exit allows:
>   - you to add one or more sets of code, at the points at which they 
> become  required, to the list of things to execute at the exit of the 
> scope in all  cases.
> 
> To achieve the same thing that on_scope gives with try/finally requires 
>  you to store state somewhere to indicate which parts of the finally 
> block  to execute, or, it requires that you define several finally 
> blocks and  nest them. Both of those options are no where near as neat 
> as on_scope.
> 
> I'm honestly baffled that people can't see the difference.
> 
> Regan

Ah.  I see what you want.  I was a bit confused about this before.  
This is just syntatic sugar to a relatively easy to write class though. 
Maybe it should be part of the standard library?

It essentially acts like a multi-homed delegate which is implicitly 
called at the end of the scope.
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);
}

It seems to me Walter's class example doesn't exactly do this justice.  
I find this fully acceptable for the few places I would use this.  The 
implicit instantiation of an object like this might be nice though, if 
it only added the extra code when it was referenced.  Which should be 
trivial to do.  I'd much rather have an "implicit" scope object than 
this, or the current syntax.

-S.
8 9 10 11 12 13 14 15 16
Top | Discussion index | About this forum | D home