February 27, 2006
Andrew Fedoniouk wrote:
> I am with Charles here...
> 
> I don't understand why
> on_scope_failure & co. are significantly better than
> try catch finally?

imho, they're not better in all cases, just in some :)

> What is wrong with them?

nothing

> Semantically try-catch-finally are well known and
> widely recognizable constructions.

agreed

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

Well, nothing in principle, but like it was said already:
- init and cleanup can be close together (which is good in itself)
- as a consequence, it's harder to forget cleanup
- it's prettier - code that is about linear looks like it's about linear (see example 2)
- you can reorder them as you see fit (see example 1)
- less typing :)


Example 1:

=======================
on_scope_exit foo();
on_scope_failure bar();
on_scope_exit baz();

// code
=======================

Versus

=======================
try {
    try {
        try {
            // code
        } finally {
            baz();
        }
    } catch (Object e) {
        bar();
        throw e;
    }
} finally {
    foo();
}
=======================


Example 2:

==================================
// notice how creation and cleanup are together
Logger log = getLogger();
on_scope_exit log.close();
on_scope_failure log.logFailure("...");

File outf = getOutputFile();
on_scope_exit outf.close();

File inf = getInputFile();
on_scope_exit inf.close();

File tmpf = createTempFile();
on_scope_exit tmpf.delete();
on_scope_exit tmpf.close();

// lots of code
==================================

Versus

==================================
Logger log = getLogger();
try {
    File outf = getOutputFile();
    try {
        File inf = getInputFile();
        try {
            File tmpf = createTempFile();
            try {
                // lots of code
            } finally {
                tmpf.close();
                tmpf.delete();
            }
        } finally {
            inf.close();
        }
    } finally {
        outf.close();
    }
} catch (Object e) {
    log.logFailure("...");
    throw e;
} finally {
    log.close();
}
==================================



February 27, 2006
"Walter Bright" <newshound@digitalmars.com> wrote in message news:dtr8kl$4lm$1@digitaldaemon.com...
>
> "Derek Parnell" <derek@psych.ward> wrote in message news:op.s5j942tp6b8z09@ginger.vic.bigpond.net.au...
>> Wow! I know of one other language that (almost) implements this.
>
> Which one?
>

If I understand this correctly Ruby has something similar http://www.rubycentral.com/book/tut_exceptions.html

But this is the same try-catch-finally I guess
as these on_scope_*** too, btw.

Andrew.


February 27, 2006
> ==================================
> Logger log = getLogger();
> try {
>     File outf = getOutputFile();
>     try {
>         File inf = getInputFile();
>         try {
>             File tmpf = createTempFile();
>             try {
>                 // lots of code
>             } finally {
>                 tmpf.close();
>                 tmpf.delete();
>             }
>         } finally {
>             inf.close();
>         }
>     } finally {
>         outf.close();
>     }
> } catch (Object e) {
>     log.logFailure("...");
>     throw e;
> } finally {
>     log.close();
> }
> ==================================
>
>

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.


February 27, 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
> 
> 

The syntax seems a little kludgey.
February 27, 2006
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
February 27, 2006
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:dtv8f5$1svn$1@digitaldaemon.com...
>
> "Walter Bright" <newshound@digitalmars.com> wrote in message news:dtr2fg$2vqr$4@digitaldaemon.com...
>> 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
>
> Note GCC has pretty much the same thing with the "cleanup" attribute extension on variables: http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Variable-Attributes.html

cleanup only corresponds with on_scope_exit, not the other two. It also only runs a function with a local variable as a parameter - i.e. it is the same thing as RAII. It doesn't allow arbitrary code to be executed, nor manage things like state of a class member, etc.


February 27, 2006
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?

-- 
Carlos Santander Bernal

February 27, 2006
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.
February 27, 2006
Aye gets my vote too.


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.
February 27, 2006
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();
>
> Yeap. It's nice. Maybe s/success/pass/ s/failure/fail/ would even improve it
> a little.

Good one.