February 28, 2006
Chris Miller wrote:
> On Sat, 25 Feb 2006 21:06:36 -0500, Walter Bright <newshound@digitalmars.com> wrote:
> 
>> 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
>>
> 
> This format looks good to me:
> 
> scope(exit)  foo();
> scope(success)  bar();
> scope(failure)  baz();
> 
> similar to extern(name), pragma(name), etc, requires one `scope` keyword, name in () doesn't need to be a keyword but is still treated special, and doesn't look bad.

Here's some more experimental ideas:

  scope.onExit fooexpr;
  scope.onSuccess barexpr;
  scope.onFailure bazexpr;

Now a more clean/pure version, but that doesn't allow block statements:

  scope.onExit(fooexpr);
  scope.onSuccess(barexpr);
  scope.onFailure(bazexpr);

Don't really 100% like them, but I'll present them anyway, maybe it will inspire someone for a better idea. (The problem with this one is that is makes scope seem like a workable proper object, while it's not)

-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
February 28, 2006
In article <du0slm$lj0$2@digitaldaemon.com>, Walter Bright says...
>
>Ruby's rescue thing looks like try-catch. on_scope is much more than try-catch, or I wouldn't have implemented it <g>.

on_scope is quite cute, and certainly cleaner than the C++ implementation of ScopeGuard. Compared to ctor/dtor RAII, though, it still has the same problem as try-catch{-finally} - a naive use of a resource is wrong by default, and the programmer has to do something extra to make it right.

When I first saw Andrei's paper it struck me that what made things painful in C++ was the lack of usable closures. Since D is pretty good in this regard, could the same effect have been achieved with a less sugary but more regular approach reusing RAII-auto syntax, e.g.

# import std.scopeguard;
# auto Guard onOk = new OnScopeSuccessGuard(&mySuccessFunc);
# auto Guard onFail = new OnScopeFailureGuard(function { /* ad hoc code */ });

with something like C++'s std::uncaught_exception in the Guard subclass destructor implementations to discriminate exit conditions?

cheers
Mike


February 28, 2006
Andrew Fedoniouk escribió:
> Hi, Carlos
> 
> "Carlos Santander" <csantander619@gmail.com> wrote in message news:dtvtgt$2mvh$1@digitaldaemon.com...
>> Andrew Fedoniouk escribió:
>>> This is real life example:
>>>
>>> Logger log = getLogger();
>>> try {
>>>       File outf = getOutputFile(); // state managed outside
>>>       File inf = getInputFile(); // state managed outside
>>>       File tmpf = createTempFile();
>>>       // lots of code
>>> } catch (Object e)  {
>>>       log.logFailure("...");
>>>       throw e;
>>> } finally {
>>>      delete tmpf;
>>> }
>>> log.close();
>>>
>>> ----------------------------------
>>> Andrew.
>>>
>>>
>> This is not rhetorical, but honest: in the cases where you said "state managed
>> outside", how do you do that? i.e., how do you know for sure that the files will
>> be closed, provided that destructors are not guaranteed to be run and you can't return auto references?
> 
> "get" in getOutputFile implies that file exists somewhere and opened by someone else
> so code here cannot delete it.
> 

If I understand correctly, then that someone else who opened the file would have to close it (or delete it, as you put it). How does the opener know when to close it?

> In contrary "create" in createTempFile says that it creates new instance
> so we are owning it - must delete.
> 
> If getOutputFile creates new instance then
> finally {
>      delete tmpf;
>      delete outf;
>      delete inf;
> }
> will be enough.
> 

See Walter's reply.

> In any case it shall be something one: either
> try-catch-finally or on_scope_xxx() - two similar
> and probably conflicting mechanisms is a bad design.
> 

Not necessarily. RAII and finally could be seen as "similar mechanisms", but I don't think having both is a bad design. How about for and foreach? do and while? function and delegate?

> ( This is why I like Java - with some minor exceptions
>  its grammar just perfect for the the domain it serves.
>  Ascetic but clean and simple. )
> 
> Andrew Fedoniouk.
> http://terrainformatica.com
> 
> 

-- 
Carlos Santander Bernal
February 28, 2006
Walter Bright wrote:
> 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
> 

This is excellent!

is it the first really new thing in D?
thinking hard (for 30 seconds) seems to be the first one.

excellent in any case.

Ant

February 28, 2006
Regan,

Your last post finally made me get it.

on_scope_* is a different kind of construct.  It's kind of like (imperfect analogy coming) descending down a dynamic ladder.  If you have to go up again on_scope_failure tells you which how to undo each "code rung" so you can go back up.  The on_scope_success adds a last rung from the floor and on_scope_exit adds codes at both ends of the ladder.  The analogy wears a bit thin because you can do on_scope_exit failure and success multiple times.

I have rtfa and all the previous messages and it still wasn't apparent that all this was possible.

Thanks,

Tom


In article <ops5n86slk23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>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


February 28, 2006
Chris Miller wrote:
<snip>
> scope(exit)  foo();
> scope(success)  bar();
> scope(failure)  baz();
> 
> similar to extern(name), pragma(name), etc, requires one `scope` keyword, name in () doesn't need to be a keyword but is still treated special, and doesn't look bad.

The scope(exit) notation gets me thinking, considering that all three of them are on exit from the scope.  Not that I can think of anything better....

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.
February 28, 2006
Regan Heath wrote:
<snip>
> 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.

When I started to read it, it did indeed look like syntactic sugar for try/finally.  But then I realised that, as you say, it saves some of the need to nest try/finally blocks.

on_scope_failure has another advantage still: if you have multiple catch blocks, it saves having to replicate the recovery code in each.

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.
February 28, 2006
Lucas Goss wrote:

>>> Chris Miller wrote:
>>>>
>>>> scope(exit)  foo();
>>>> scope(success)  bar();
>>>> scope(failure)  baz();
>>>
> 
> While I don't really like the _'s in on_scope_exit, etc, I don't like this proposed syntax any more, in fact I think I don't like it as much. With this proposed syntax it seems like an expression such as an if/while/for/etc, however, in all of those the condition is user defined. So this proposed syntax would appear inconsistent.
> 
> <rant>
> And if there's one thing I dislike in languages and libraries, it's
> inconsistencies, right up with it is non descriptive or inconsistent
> functions. Don't even get me started on those, I'm looking at you Phobos
> :)
> 
> writefln ... what? write file name? write first line? write f language?
> isxdigit ... is x a digit? of course not! why do I need this function?
> pardir   ... parrot directory? not everyone has the parrot vm.
> altsep   ... Alt key seperator? does this get the Alt key?
> ifind    ... integer find? iFind? iWork? is this for Mac only?
> 
> First, I don't see why all of the above aren't readable. And second, why don't they follow the D guidelines of camelCase? (I prefer the PascalCase myself, but I could live with camelCase if it was consistent). For example:
> 
> writeLine(string), writeLine(string, format)
> isHexDigit
> parentDirectory
> windowsAlternateSeperator
> FindFirst
> 
> The only reason I can see is "it will make it easier for C/C++ programmers." or, it's shorter. The first has little merit, as templates, operator overloading, streams, reals etc. are all different (for good reason of course), and C/C++ programmers will have to learn D no matter what. As for shorter, you may gain a few seconds (after a couple hundred lines), but I'd much rather be able to tell what I was doing at a glance...
> 
> (notice: Yes I know, the functions come from C... it's good we hold on
> to our history just like C++ did :) )
> </rant>
> 
> I'd much rather prefer something like:
> scopeexit
> scopesuccess
> scopefailure
> 
> Or some derivative:
> scopeabort, scopefault, scopedone, scopefinish, scope?
> 
> ps. I like the looks of this new feature and find it very elegant. I prefer this to try/catch/finally.

Sorry, but I find the proposed statements very consistent with D's existing version, debug, etc statements.
February 28, 2006
Walter Bright wrote:
> "Andrew Fedoniouk" <news@terrainformatica.com> wrote in message news:du106f$ptt$1@digitaldaemon.com...
>> Well, I spent year programming on PocketPC in eVC where are no such
>> things as exceptions. In principle. Not implemented in C++ compiler.
>> Still alive :)
> 
> It's true that if code doesn't generate exceptions, then one doesn't need exception safety.

It's worth mentioning that an allocation failure will cause an exception to be thrown, in addition to divide by zero and other errors on Windows.  So code doesn't need to explicitly throw to generate exceptions.

The PocketPC really doesn't have exceptions?  And they still call it C++? :-)

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


Sean
February 28, 2006
"Mike Capp" <mike.capp@gmail.com> wrote in message news:du1ire$1h1s$1@digitaldaemon.com...
> When I first saw Andrei's paper it struck me that what made things painful
> in
> C++ was the lack of usable closures. Since D is pretty good in this
> regard,
> could the same effect have been achieved with a less sugary but more
> regular
> approach reusing RAII-auto syntax, e.g.
>
> # import std.scopeguard;
> # auto Guard onOk = new OnScopeSuccessGuard(&mySuccessFunc);
> # auto Guard onFail = new OnScopeFailureGuard(function { /* ad hoc code
> */ });
>
> with something like C++'s std::uncaught_exception in the Guard subclass destructor implementations to discriminate exit conditions?

I don't know a way to make that work as cleanly.