February 28, 2006
Dawid Ciężarkiewicz wrote:
> Chris Miller wrote:
> 
> 
>>This format looks good to me:
>>
>>scope(exit)  foo();
>>scope(success)  bar();
>>scope(failure)  baz();
> 
> 
> Yeap. It's nice. Maybe s/success/pass/ s/failure/fail/ would even improve it
> a little.


The proposed syntax feels like D. Count my vote.
February 28, 2006
clayasaurus wrote:
> 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
>>
>>
> 
> The syntax seems a little kludgey.

The Rubyish style hurts my eyes.
February 28, 2006
Walter Bright wrote:
> "Hasan Aljudy" <hasan.aljudy@gmail.com> wrote in message news:dtsfm5$1h2i$1@digitaldaemon.com...
> 
>>Why not just reuse "finally"?
>>
>>void func()
>>{
>>    init_some_reource();
>>    foo(); // foo throws an exception
>>    //func doesn't catch the exception
>>    //but it has a finally clause
>>
>>    finally  //aka on scope exit, whether success or fail
>>    {
>>        release_the_resource();
>>    }
>>}
> 
> 
> finally does work for on_scope_exit, but it leaves on_scope_success and on_scope_failure hanging. 
> 
> 

Why do we need to handle "on failure" and "on success" any differently than a regular scope exit?
February 28, 2006
Hasan Aljudy wrote:
> 
> Why do we need to handle "on failure" and "on success" any differently than a regular scope exit?

See the "transaction processing" examples here: http://www.digitalmars.com/d/exception-safe.html


Sean
February 28, 2006
>> 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.
February 28, 2006
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.

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.

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.

( 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


February 28, 2006
"Regan Heath" <regan@netwin.co.nz> wrote in message news:ops5nhbgii23k2f5@nrage.netwin.co.nz...
> On Mon, 27 Feb 2006 10:42:10 -0800, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>> I am with Charles here...
>>
>> I don't understand why
>> on_scope_failure & co. are significantly better than
>> try catch finally?
>>
>> What is wrong with them?
>>
>> Semantically try-catch-finally are well known and
>> widely recognizable constructions.
>>
>> BTW: Am I right in my assumption that
>> proposed on_scope_exit / on_scope_success / on_scope_failure
>> is a direct equivalent of the following:
>>
>> try
>> {
>>    [scope code]
>>    my_on_scope_success().
>> }
>> catch(...)
>> {
>>    my_on_scope_failure().
>> }
>> finally {
>>   my_on_scope_exit().
>> }
>>
>> If yes then again what it wrong with them in principle?
>
> For a simple example it is very similar, for a more complex one it's not.
> Have you read this:
>   http://www.digitalmars.com/d/exception-safe.html
>
> Here is my attempt at "explaination by example", a more complex example and it's equivalent using try/catch/finally.
>
> Transaction abc()
> {
>     Foo f;
>     Bar b;
>     Def d;
>
>     f = dofoo();
>     on_scope_failure dofoo_unwind(f);
>
>     b = dobar();
>     on_scope_failure dobar_unwind(b);
>
>     d = dodef();
>
>     return Transaction(f, b, d);
> }
>
> as try/catch/finally:
>
> Transaction abc()
> {
> Foo f;
> Bar b;
> Def d;
>
> f = dofoo(); try {
> b = dobar();
> try {
> d = dodef();
> return Transaction(f, b, d);
> }
> catch(Object o) {
> dobar_unwind(b);
> throw o;
> }
> }
> catch(Object o) {
> dofoo_unwind(f);
> throw o;
> } }
>
> Note, the order of the unwind calls is important:
>   http://www.digitalmars.com/d/statement.html#scope
>   "If there are multiple OnScopeStatements in a scope, they are executed
> in the reverse lexical order in which they appear."
>
> There are many benefits of on_scope over try/catch, they are:
>
> 1. less verbose, with less clutter it's easier to see the purpose of the code. on scope scales well to handle many 'transactions' which require cleanup, like the example above, try/catch/finally does not, it gets horribly nested and confusing.
>
> 2. groups the cleanup code with code that requires it, less seperation between the thing that is done, and the thing that cleans up after it. try/catch/finally has the cleanup code in a seperate 'catch' or 'finally' scope often a long way from the code that creates the need for that cleanup.
>
> Regan

Seems like I realy don't understand something here...

Why you think that your example is aesthetically
better (technically they are the same) than this?

Transaction abc()
{
    Foo f;   Bar b;  Def d;
    try
   {
       f = dofoo();
       b = dobar();
       d = dodef();
       return Transaction(f, b, d);
   }
   finally {
      delete f; delete b; delete d;
   }
}

I can easily accept on_scope_failure if
it would solve something in principle.
But so far it is a reformulation of VBs onerror/resume as
far as I can see.

Andrew Fedoniouk.
http://terrainformatica.com


February 28, 2006
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.

February 28, 2006
On Mon, 27 Feb 2006 19:54:23 -0800, Andrew Fedoniouk <news@terrainformatica.com> wrote:
> Seems like I realy don't understand something here...
>
> Why you think that your example is aesthetically
> better (technically they are the same) than this?

Wait, your example below is not technically the same as mine because:

1. My example (actually taken from the docs on digitalmars.com) used on_scope_failure, not on_scope_exit. on_scope_exit has the same effect as "finally" except...

2. The important feature of all of these statements is that they allow you to add items to the list of things to do _as you go_ and to then execute them in reverse lexical order at the appropriate time i.e. on_scope_exit or on_scope_failure etc.

The same cannot be achieved with catch or finally without nesting several of them. That is what the example I gave was designed to show I believe.

> Transaction abc()
> {
>     Foo f;   Bar b;  Def d;
>     try
>    {
>        f = dofoo();
>        b = dobar();
>        d = dodef();
>        return Transaction(f, b, d);
>    }
>    finally {
>       delete f; delete b; delete d;
>    }
> }

For the fun of it, lets re-write your example to use on_scope_exit:

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

   f = dofoo();
   on_scope_exit delete f;

   b = dobar();
   on_scope_exit delete b;

   d = dodef();
   on_scope_exit delete d;

   return Transaction(f, b, d);
}

I believe this is better that your try/finally example because:

 1- delete is not called on an unitialized class reference as in your example. (thankfully D initialises them to null)
 2- the init and delete of each object is in the same place (the larger the block of code this is used in, the better it gets).
 3- the resulting code is linear, which is easier to follow than some branching, indented, or nested try/catch/finally block.

Regan
February 28, 2006
On Mon, 27 Feb 2006 21:05:33 -0800, S. Chancellor <dnewsgr@mephit.kicks-ass.org> wrote:
> 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.

You honestly don't think that this:

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

    f = dofoo();
    on_scope_failure dofoo_unwind(f);

    b = dobar();
    on_scope_failure dobar_unwind(b);

    d = dodef();

    return Transaction(f, b, d);
}

is better than this:

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

  f = dofoo();
  try {
    b = dobar();
    try {
      d = dodef();
      return Transaction(f, b, d);
    }
    catch(Object o) {
      dobar_unwind(b);
      throw o;
    }
  }
  catch(Object o) {
    dofoo_unwind(f);
    throw o;
  }
}

Regan