www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - why scope(success)?

reply "Ben Hinkle" <bhinkle mathworks.com> writes:
I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
scope(success) and why. I can't find any reason for it.

Some background: I've slowed my D work to focus on some C experimental 
features I'm calling Cx: http://www.tinycx.org and currently I'm 
implementing the error handling using reserved labels "error:" and 
"finally:". The error label is roughly like scope(failure) and the finally 
label is roughly like scope(exit). There's no try-catch-finally. I don't 
plan on adding anything like scope(success) because I couldn't think of why 
anyone would want to use it. Why not just put the code at the end of the 
scope like normal code-flow? I suppose one could code the entire scope in 
reverse just for kicks:
void main() {
  scope(success) printf("world\n");
  scope(success) printf("hello ");
}

-Ben 
May 09 2006
next sibling parent BCS <BCS pathlink.com> writes:
Ben Hinkle wrote:
 I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
 scope(success) and why. I can't find any reason for it.
 
 Some background: I've slowed my D work to focus on some C experimental 
 features I'm calling Cx: http://www.tinycx.org and currently I'm 
 implementing the error handling using reserved labels "error:" and 
 "finally:". The error label is roughly like scope(failure) and the finally 
 label is roughly like scope(exit). There's no try-catch-finally. I don't 
 plan on adding anything like scope(success) because I couldn't think of why 
 anyone would want to use it. Why not just put the code at the end of the 
 scope like normal code-flow? I suppose one could code the entire scope in 
 reverse just for kicks:
 void main() {
   scope(success) printf("world\n");
   scope(success) printf("hello ");
 }
 
 -Ben 
 
 

int fn(int i) { scope(success) printf("Good\n"); scope(failure) printf("Bad\n"); /* big huge logic block with a bazillion returns and throws +/ }
May 09 2006
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Ben Hinkle wrote:
 I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
 scope(success) and why. I can't find any reason for it.

How about a DB transaction you only want to commit if there are no errors generating data. You might want something like this: scope(success) tran.commit(); scope(failure) tran.rollback(); Sean
May 09 2006
parent reply Serg Kovrov <dyh pathlink.com> writes:
I used to manage it with exceptions, and more or less happy with it:
 deleteNode(node_id)
 {
   node = getNode(node_id);
   if (!node || !db.hasSQLFeature(SQL_TRANSACTIONS))
   {
     return false;
   }
 
   db.beginTransaction();
   try
   {
     ...
     lots of stuf that may throw,
     or maybe throw something right here...
     ...
   }
   catch (Exception e)
   {
     db.rollbackTransaction();
     return false;
   }
 
   db.commitTransaction();
   return true;
 }

In this particular case I don't want rollback on returning false, just if a db operation failed. And exceptions handle that rather well. My point is, if case is a bit more complicated then a 'hello world' example, there most likely will be different error conditions, and they meant be handled differently. Exceptions are convenient way to do it. IMHO 'on scope exit' approach is not much different from 'one return at end of function' with condition flag(s). And it is kind of obscure code for me - it can be anywhere in function, maybe even may times, etc... It's hard to maintain (just like goto's), and as so, it's no use for me at this point. Sean Kelly wrote:
 Ben Hinkle wrote:
 I hope this doesn't come of as a flame, but I'm wondering if anyone is 
 using scope(success) and why. I can't find any reason for it.

How about a DB transaction you only want to commit if there are no errors generating data. You might want something like this: scope(success) tran.commit(); scope(failure) tran.rollback(); Sean

May 10 2006
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Serg Kovrov wrote:
 
 IMHO 'on scope exit' approach is not much different from 'one return at 
 end of function' with condition flag(s).

True. But if the function is complex and has multiple return points, scope(success) is easier to maintain.
 And it is kind of obscure code for me - it can be anywhere in function, 
 maybe even may times, etc... It's hard to maintain (just like goto's), 
 and as so, it's no use for me at this point.

It's a matter of opinion, I suppose. I find scope declarations more visible and more meaningful than the alternatives. And I like that I can place them next to the declarations of data they're meant to affect, thus making the code more meaningful. Sean
May 10 2006
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 And it is kind of obscure code for me - it can be anywhere in function, 
 maybe even may times, etc... It's hard to maintain (just like goto's), 
 and as so, it's no use for me at this point.

It's a matter of opinion, I suppose. I find scope declarations more visible and more meaningful than the alternatives. And I like that I can place them next to the declarations of data they're meant to affect, thus making the code more meaningful. Sean

Are you using them in practice? Is there a link I can follow to see the code? TIA
May 10 2006
parent Sean Kelly <sean f4.ca> writes:
Ben Hinkle wrote:
 And it is kind of obscure code for me - it can be anywhere in function, 
 maybe even may times, etc... It's hard to maintain (just like goto's), 
 and as so, it's no use for me at this point.

visible and more meaningful than the alternatives. And I like that I can place them next to the declarations of data they're meant to affect, thus making the code more meaningful.

Are you using them in practice? Is there a link I can follow to see the code?

scope(success)? Not yet. I've only used scope(failure) and scope(exit) so far: http://svn.dsource.org/projects/ares/trunk/src/ares/std/array.d http://svn.dsource.org/projects/ares/trunk/src/ares/std/thread.d I do think the use of scope(success) is fairly limited--the DB example is one of the I can think of--but it's a nice option to have. Sean
May 10 2006
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Serg Kovrov wrote:
 In this particular case I don't want rollback on returning false, just 
 if a db operation failed. And exceptions handle that rather well.
 
 My point is, if case is a bit more complicated then a 'hello world' 
 example, there most likely will be different error conditions, and they 
 meant be handled differently. Exceptions are convenient way to do it.

Exceptions work well as long as there is only one operation that needs to be rolled back. As soon as you have two or more operations that happen sequentially, and either both must succeed or neither, that the traditional exception mechanism starts coming unglued. For example, if I have operations A(), B(), and C(), and A.rollback(), B.rollback() and C.rollback: A(); scope(failure) A.rollback(); B(); scope(failure) B.rollback(); C(); scope(failure) C.rollback(); Just for fun, try to do that with either C++ exceptions or Java try-finally.
May 12 2006
parent reply Mike Capp <mike.capp gmail.com> writes:
In article <e42jr6$2u07$1 digitaldaemon.com>, Walter Bright says...
For example, if I have operations A(), B(), and C(), and A.rollback(), 
B.rollback() and C.rollback:

	A();
	scope(failure) A.rollback();
	B();
	scope(failure) B.rollback();
	C();
	scope(failure) C.rollback();

Just for fun, try to do that with either C++ exceptions or Java try-finally.

Off the top of my head... struct A // ditto for B and C { A() { doA(); } ~A() { if (std::uncaught_exception()) { rollbackA(); } } }; A a; B b; C c; I'm sure there are drawbacks; there always are. It's horses for courses. If the operations are common ones, the C++ approach wins out IMHO because you don't have to remember the scope statement (which is still a "wrong by default" design). If the operation is an ad-hoc one and you have to write the wrapper class yourself, the D approach is much cleaner since it keeps everything together and clarifies the intent. (Just look how popular std::for_each isn't.) cheers Mike
May 13 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Mike Capp wrote:
 In article <e42jr6$2u07$1 digitaldaemon.com>, Walter Bright says...
 For example, if I have operations A(), B(), and C(), and A.rollback(), 
 B.rollback() and C.rollback:

 	A();
 	scope(failure) A.rollback();
 	B();
 	scope(failure) B.rollback();
 	C();
 	scope(failure) C.rollback();

 Just for fun, try to do that with either C++ exceptions or Java try-finally.

Off the top of my head... struct A // ditto for B and C { A() { doA(); } ~A() { if (std::uncaught_exception()) { rollbackA(); } } }; A a; B b; C c;

This doesn't work because when the scope is done, no matter how it ends, A, B and C are *all* rolled back. The idea is that if the scope exits normally, A, B and C are *not* rolled back. The starting point for C++ would be: A* a = new A(); B* b = new B(); C* c = new C(); I need all three to succeed or none. Think of something like a database transactions, where 3 different places in the database have to be updated as one operation. You can't leave it as 1 done, or 2 done. It has to be all 3, or none of them.
May 13 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Walter Bright wrote:

 This doesn't work because when the scope is done, no matter how it ends, 
 A, B and C are *all* rolled back.

Eh, I misinterpreted Mike's code. Sorry. But the uncaught_exception doesn't do the job. It only gets invoked if some exception is uncaught anywhere on the call stack, not if it is just uncaught before the destructors are called.
May 13 2006
parent Mike Capp <mike.capp gmail.com> writes:
In article <e45cvg$cib$2 digitaldaemon.com>, Walter Bright says...
Walter Bright wrote:

Eh, I misinterpreted Mike's code. Sorry.

Quite all right. I misinterpret my code all the time.
But the uncaught_exception doesn't do the job. It only gets invoked if 
some exception is uncaught anywhere on the call stack, not if it is just 
uncaught before the destructors are called.

Oops. I stand corrected. cheers Mike
May 14 2006
prev sibling parent Sean Kelly <sean f4.ca> writes:
Mike Capp wrote:
 In article <e42jr6$2u07$1 digitaldaemon.com>, Walter Bright says...
 For example, if I have operations A(), B(), and C(), and A.rollback(), 
 B.rollback() and C.rollback:

 	A();
 	scope(failure) A.rollback();
 	B();
 	scope(failure) B.rollback();
 	C();
 	scope(failure) C.rollback();

 Just for fun, try to do that with either C++ exceptions or Java try-finally.

Off the top of my head... struct A // ditto for B and C { A() { doA(); } ~A() { if (std::uncaught_exception()) { rollbackA(); } } };

It's probably a matter of implementation, but std::uncaught_exception isn't terribly useful in C++. The most obvious reason being that it acts globally rather than specific to the calling thread. I'm also not sure I like that the dtor would change behavior based on whether an exception is in flight. This results in unexpected behavior, which is never a good thing. Sean
May 13 2006
prev sibling next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <e3qpsj$igc$1 digitaldaemon.com>, Ben Hinkle says...
I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
scope(success) and why. I can't find any reason for it.

Some background: I've slowed my D work to focus on some C experimental 
features I'm calling Cx: http://www.tinycx.org and currently I'm 
implementing the error handling using reserved labels "error:" and 
"finally:". The error label is roughly like scope(failure) and the finally 
label is roughly like scope(exit). There's no try-catch-finally. I don't 
plan on adding anything like scope(success) because I couldn't think of why 
anyone would want to use it. Why not just put the code at the end of the 
scope like normal code-flow? I suppose one could code the entire scope in 
reverse just for kicks:
void main() {
  scope(success) printf("world\n");
  scope(success) printf("hello ");
}

-Ben 

I'm considering using it for some code generation technqiues (parsers mostly). Being able to declare what happens at the tail-end of a scope *first*, rather than last, means that you have to maintain less state (across nested scopes) in your code generator. - EricAnderton at yahoo
May 09 2006
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 I'm considering using it for some code generation technqiues (parsers 
 mostly).

 Being able to declare what happens at the tail-end of a scope *first*, 
 rather
 than last, means that you have to maintain less state (across nested 
 scopes) in
 your code generator.

 - EricAnderton at yahoo

Ok. That sounds like an interesting application. If it comes on line sometime soon let me know.
May 09 2006
parent pragma <pragma_member pathlink.com> writes:
In article <e3qvhn$q3v$1 digitaldaemon.com>, Ben Hinkle says...
 I'm considering using it for some code generation technqiues (parsers 
 mostly).

 Being able to declare what happens at the tail-end of a scope *first*, 
 rather
 than last, means that you have to maintain less state (across nested 
 scopes) in
 your code generator.

 - EricAnderton at yahoo

Ok. That sounds like an interesting application. If it comes on line sometime soon let me know.

Sure. Although the use of scope() here is really just theoretical at this point... I have something that digests EBNF (w/some annotations) to build a self-hosting parser frontend, but it makes heavy use of exceptions and anon delegates. I'm pretty sure that I can make some of the pass/fail semantics of the various parse expressions more straightforward (almost as much as goto) by way of scope(), but I haven't tried it yet. // I'll let y'all know what's up when I get there, regardless. :) - EricAnderton at yahoo
May 09 2006
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 9 May 2006 15:17:38 -0400, Ben Hinkle <bhinkle mathworks.com>  
wrote:

 I hope this doesn't come of as a flame, but I'm wondering if anyone is  
 using
 scope(success) and why. I can't find any reason for it.

 Some background: I've slowed my D work to focus on some C experimental
 features I'm calling Cx: http://www.tinycx.org and currently I'm
 implementing the error handling using reserved labels "error:" and
 "finally:". The error label is roughly like scope(failure) and the  
 finally
 label is roughly like scope(exit). There's no try-catch-finally. I don't
 plan on adding anything like scope(success) because I couldn't think of  
 why
 anyone would want to use it. Why not just put the code at the end of the
 scope like normal code-flow? I suppose one could code the entire scope in
 reverse just for kicks:
 void main() {
   scope(success) printf("world\n");
   scope(success) printf("hello ");
 }

Maybe... self documenting functions, listing all return values at the top? int foobar( ..etc.. ) { scope(success) return 1; scope(failure) return 0; } As someone else mentioned, commiting changes to a database, perhaps several, some of which are optional depending on program flow eg. int foobar( ..etc..) { if (a) { ..make changes to a.. scope(success) db.commit(a); } if (b) { ..make changes to b.. scope(success) db.commit(b); } ..make changes to c.. db.commit(c); //no scope.. required here return 1; } Regan
May 09 2006
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 Maybe... self documenting functions, listing all return values at the top?

 int foobar( ..etc.. )
 {
   scope(success) return 1;
   scope(failure) return 0;

 }

Does scope(failure) continue unwinding the stack? I wonder what the behavior is of returning from a scope(failure).
 As someone else mentioned, commiting changes to a database, perhaps 
 several, some of which are optional depending on program flow eg.

 int foobar( ..etc..)
 {
   if (a) {
     ..make changes to a..
     scope(success) db.commit(a);
   }

   if (b) {
     ..make changes to b..
     scope(success) db.commit(b);
   }

   ..make changes to c..
   db.commit(c); //no scope.. required here
   return 1;
 }

I believe writing "scope(success) foo;" followed by the end of the current scope is equivalent to just writing "foo;". Maybe I'm misunderstanding the example.
 Regan 

May 09 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 9 May 2006 22:36:03 -0400, Ben Hinkle <ben.hinkle gmail.com> wrote:
 Maybe... self documenting functions, listing all return values at the  
 top?

 int foobar( ..etc.. )
 {
   scope(success) return 1;
   scope(failure) return 0;

 }

Does scope(failure) continue unwinding the stack? I wonder what the behavior is of returning from a scope(failure).

Good question. No idea. :(
 I believe writing "scope(success) foo;" followed by the end of the  
 current scope is equivalent to just writing "foo;". Maybe I'm  
 misunderstanding the example.

You're right. For some reason I got it in my head that scope(success) happened when the function itself returned, as opposed to the current scope closing. So, what about in this case: int foobar( ..etc ..) { if (a) scope(success) a.foo(); //A: immediately after if } //B: at function return when does a.foo() get executed? at A or B? I get the impression it's A. Regan
May 09 2006
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Regan Heath wrote:
 On Tue, 9 May 2006 22:36:03 -0400, Ben Hinkle <ben.hinkle gmail.com> wrote:
 
 Maybe... self documenting functions, listing all return values at 
 the  top?

 int foobar( ..etc.. )
 {
   scope(success) return 1;
   scope(failure) return 0;

 }

Does scope(failure) continue unwinding the stack? I wonder what the behavior is of returning from a scope(failure).

Good question. No idea. :(
 I believe writing "scope(success) foo;" followed by the end of the  
 current scope is equivalent to just writing "foo;". Maybe I'm  
 misunderstanding the example.

You're right. For some reason I got it in my head that scope(success) happened when the function itself returned, as opposed to the current scope closing. So, what about in this case: int foobar( ..etc ..) { if (a) scope(success) a.foo(); //A: immediately after if } //B: at function return when does a.foo() get executed? at A or B? I get the impression it's A. Regan

Evidence from testing is that a.foo() is executed at point A. Which I think is a shame, really. It limits the usefulness of the scope() statement, which I feel is otherwise full of potential. Maybe its a little silly to say aloud, but certain statements just shouldn't "be a scope" for the sake of the scope() statement. Maybe different scopes should have "weights" or something... I don't know how it should be done, just that it should, or else a way created to say which scope you are anchoring on, but what on earth would the syntax be? -- Chris Nicholson-Sauls
May 10 2006
prev sibling next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
Regan Heath wrote:
 On Tue, 9 May 2006 22:36:03 -0400, Ben Hinkle <ben.hinkle gmail.com> wrote:
 I believe writing "scope(success) foo;" followed by the end of the  
 current scope is equivalent to just writing "foo;". Maybe I'm  
 misunderstanding the example.

You're right. For some reason I got it in my head that scope(success) happened when the function itself returned, as opposed to the current scope closing. So, what about in this case: int foobar( ..etc ..) { if (a) scope(success) a.foo(); //A: immediately after if } //B: at function return when does a.foo() get executed? at A or B? I get the impression it's A. Regan

if statements do not create a scope without { }, therefore it should be at B. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M-- V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++ ------END GEEK CODE BLOCK------ James Dunne
May 10 2006
parent reply Sean Kelly <sean f4.ca> writes:
James Dunne wrote:
 
 if statements do not create a scope without { }, therefore it should be 
 at B.

They don't? Sean
May 10 2006
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message 
news:e3tjf6$1v3n$1 digitaldaemon.com...
 James Dunne wrote:
 if statements do not create a scope without { }, therefore it should be 
 at B.

They don't? Sean

They do. The code if (1) int a = 10; a = 20; is illegal.
May 10 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
Ben Hinkle wrote:
 "Sean Kelly" <sean f4.ca> wrote in message 
 news:e3tjf6$1v3n$1 digitaldaemon.com...
 
James Dunne wrote:

if statements do not create a scope without { }, therefore it should be 
at B.

They don't? Sean

They do. The code if (1) int a = 10; a = 20; is illegal.

Then the implementation according to D's language specs is incorrect. Nothing is mentioned about new scopes created by if-statements or while-statements. New scopes are only created from block { } statements when inside a function body. Scope is mentioned (in passing) for the for-statement; the initializer is noted as a special case. Did I miss a blanket statement somewhere else in the docs about this? -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M-- V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++ ------END GEEK CODE BLOCK------ James Dunne
May 11 2006
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
James Dunne wrote:
<snip>
 Then the implementation according to D's language specs is incorrect. 
 Nothing is mentioned about new scopes created by if-statements or 
 while-statements.  New scopes are only created from block { } statements 
 when inside a function body.  Scope is mentioned (in passing) for the 
 for-statement; the initializer is noted as a special case.  Did I miss a 
 blanket statement somewhere else in the docs about this?

I think you're meant to use a bit of common sense here. What sense does it make for a declaration to be conditional at runtime? To be honest, I think a naked declaration as the body of a runtime control statement should be illegal. 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.
May 11 2006
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:e3vkhn$1kq5$1 digitaldaemon.com...
 James Dunne wrote:
 <snip>
 Then the implementation according to D's language specs is incorrect. 
 Nothing is mentioned about new scopes created by if-statements or 
 while-statements.  New scopes are only created from block { } statements 
 when inside a function body.  Scope is mentioned (in passing) for the 
 for-statement; the initializer is noted as a special case.  Did I miss a 
 blanket statement somewhere else in the docs about this?

I think you're meant to use a bit of common sense here. What sense does it make for a declaration to be conditional at runtime? To be honest, I think a naked declaration as the body of a runtime control statement should be illegal. Stewart.

You're probably right. I had tried dmc and cl and they both complained about the use of 'a' without a declaration but in fact I was expecting an error that a declaration can't be the body of an 'if' statement. Since both compiler didn't say boo about the declaration I figured that declarations are considered statements. The C99 spec doesn't consider a declaration a statement so I suspect the compilers are giving poor errors.
May 11 2006
parent reply Sean Kelly <sean f4.ca> writes:
Ben Hinkle wrote:
 "Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
 news:e3vkhn$1kq5$1 digitaldaemon.com...
 James Dunne wrote:
 <snip>
 Then the implementation according to D's language specs is incorrect. 
 Nothing is mentioned about new scopes created by if-statements or 
 while-statements.  New scopes are only created from block { } statements 
 when inside a function body.  Scope is mentioned (in passing) for the 
 for-statement; the initializer is noted as a special case.  Did I miss a 
 blanket statement somewhere else in the docs about this?

it make for a declaration to be conditional at runtime? To be honest, I think a naked declaration as the body of a runtime control statement should be illegal.

You're probably right. I had tried dmc and cl and they both complained about the use of 'a' without a declaration but in fact I was expecting an error that a declaration can't be the body of an 'if' statement. Since both compiler didn't say boo about the declaration I figured that declarations are considered statements. The C99 spec doesn't consider a declaration a statement so I suspect the compilers are giving poor errors.

What about this: if( auto i = doSomething() ) printError( i ); I don't think anyone would expect 'i' to survive after the printError expression. Sean
May 11 2006
parent James Dunne <james.jdunne gmail.com> writes:
Sean Kelly wrote:
 Ben Hinkle wrote:
 
 "Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
 news:e3vkhn$1kq5$1 digitaldaemon.com...

 James Dunne wrote:
 <snip>

 Then the implementation according to D's language specs is 
 incorrect. Nothing is mentioned about new scopes created by 
 if-statements or while-statements.  New scopes are only created from 
 block { } statements when inside a function body.  Scope is 
 mentioned (in passing) for the for-statement; the initializer is 
 noted as a special case.  Did I miss a blanket statement somewhere 
 else in the docs about this?

I think you're meant to use a bit of common sense here. What sense does it make for a declaration to be conditional at runtime? To be honest, I think a naked declaration as the body of a runtime control statement should be illegal.

You're probably right. I had tried dmc and cl and they both complained about the use of 'a' without a declaration but in fact I was expecting an error that a declaration can't be the body of an 'if' statement. Since both compiler didn't say boo about the declaration I figured that declarations are considered statements. The C99 spec doesn't consider a declaration a statement so I suspect the compilers are giving poor errors.

What about this: if( auto i = doSomething() ) printError( i ); I don't think anyone would expect 'i' to survive after the printError expression. Sean

Straight from the docs: "If an auto Identifier is provided, it is declared and initialized to the value and type of the Expression. Its scope extends from when it is initialized to the end of the ThenStatement." It's buried in there that an implicit scope is created for these cases, but nothing whatsoever is said about scope for a straight "if (expression) not-block-statement". As you noted earlier, this is a corner case where one would expect a declaration-statement to be illegal as an if-statement's body. Declaration-statements really aren't statements, they're just parsed that way to alleviate complexity. -- Regards, James Dunne
May 11 2006
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Stewart Gordon wrote:
 <snip>
 
 To be honest, I think a naked declaration as the body of a runtime
 control statement should be illegal.
 

You just reminded me of a feature of a language called Nemerle (which is a functional superset of C#): it has three conditional statements: if ... else ... where ... unless ... The thing here is that if you use "if", you must also have an "else" clause. "where" and "unless" are equivalent to "if(cond) ..." and "if(!cond) ..." in D. The rationale behind this is that it solves the problem of ambiguous chains of if/else. I actually always liked this, but am yet to see it in any other language. Speaking of neat stuff Nemerle does: "var" for type inference and immutable variables ;) -- Daniel -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 12 2006
prev sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
On Wed, 10 May 2006 00:39:30 -0400, Regan Heath <regan netwin.co.nz> wrote:

 You're right. For some reason I got it in my head that scope(success)  
 happened when the function itself returned, as opposed to the current  
 scope closing.

 So, what about in this case:

 int foobar( ..etc ..)
 {
    if (a) scope(success) a.foo();
    //A: immediately after if
 }
 //B: at function return

 when does a.foo() get executed? at A or B? I get the impression it's A.

 Regan

This gives me an idea, how about if there was scope(none) that is just like a regular block, but doesn't create a new scope. This would be for when you only need to group statements but have no interest in a new scope. void foo() { if(a) scope(none) { stuff(); scope(success) bar(); } baz(); } bar() would execute after baz(); - Chris
May 10 2006
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Chris Miller wrote:
 
 This gives me an idea, how about if there was scope(none) that is just 
 like a regular block, but doesn't create a new scope. This would be for 
 when you only need to group statements but have no interest in a new scope.
 
 void foo()
 {
    if(a) scope(none) { stuff(); scope(success) bar(); }
    baz();
 }
 
 bar() would execute after baz();

It's a nasty hack, but: if(!a) goto blah; scope(success) a.foo(); blah: ... Sean
May 10 2006
next sibling parent reply "Derek Parnell" <derek psych.ward> writes:
On Thu, 11 May 2006 08:13:37 +1000, Sean Kelly <sean f4.ca> wrote:

 Chris Miller wrote:
  This gives me an idea, how about if there was scope(none) that is just  
 like a regular block, but doesn't create a new scope. This would be for  
 when you only need to group statements but have no interest in a new  
 scope.
  void foo()
 {
    if(a) scope(none) { stuff(); scope(success) bar(); }
    baz();
 }
  bar() would execute after baz();

It's a nasty hack, but: if(!a) goto blah; scope(success) a.foo(); blah: ...

And I guess this is just as nasty ... scope(success) if (a) a.foo(); -- Derek Parnell Melbourne, Australia
May 10 2006
parent reply Sean Kelly <sean f4.ca> writes:
Derek Parnell wrote:
 On Thu, 11 May 2006 08:13:37 +1000, Sean Kelly <sean f4.ca> wrote:
 
 Chris Miller wrote:
  This gives me an idea, how about if there was scope(none) that is 
 just like a regular block, but doesn't create a new scope. This would 
 be for when you only need to group statements but have no interest in 
 a new scope.
  void foo()
 {
    if(a) scope(none) { stuff(); scope(success) bar(); }
    baz();
 }
  bar() would execute after baz();

It's a nasty hack, but: if(!a) goto blah; scope(success) a.foo(); blah: ...

And I guess this is just as nasty ... scope(success) if (a) a.foo();

Preferable so long as the state of a is maintained until scope exit. But all of this smacks as an attempt to use the scope feature in a manner that wasn't intended. Sean
May 10 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 10 May 2006 15:52:36 -0700, Sean Kelly <sean f4.ca> wrote:
 Derek Parnell wrote:
 On Thu, 11 May 2006 08:13:37 +1000, Sean Kelly <sean f4.ca> wrote:

 Chris Miller wrote:
  This gives me an idea, how about if there was scope(none) that is  
 just like a regular block, but doesn't create a new scope. This would  
 be for when you only need to group statements but have no interest in  
 a new scope.
  void foo()
 {
    if(a) scope(none) { stuff(); scope(success) bar(); }
    baz();
 }
  bar() would execute after baz();

It's a nasty hack, but: if(!a) goto blah; scope(success) a.foo(); blah: ...

scope(success) if (a) a.foo();

Preferable so long as the state of a is maintained until scope exit. But all of this smacks as an attempt to use the scope feature in a manner that wasn't intended.

Yeah. It's a pity though. What about: int foobar( .. ) { if (a) { scope(success) scope(success) a.foo(); } } I wonder. Regan
May 10 2006
prev sibling parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message 
news:e3toih$26v4$1 digitaldaemon.com...
 Chris Miller wrote:
 This gives me an idea, how about if there was scope(none) that is just 
 like a regular block, but doesn't create a new scope. This would be for 
 when you only need to group statements but have no interest in a new 
 scope.

 void foo()
 {
    if(a) scope(none) { stuff(); scope(success) bar(); }
    baz();
 }

 bar() would execute after baz();

It's a nasty hack, but: if(!a) goto blah; scope(success) a.foo(); blah: ...

In Cx I was going to make that illegal - much like in C++ it's illegal to goto past an initializer or into a try block.
 Sean 

May 10 2006
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Chris Miller wrote:
<snip>
 void foo()
 {
    if(a) scope(none) { stuff(); scope(success) bar(); }
    baz();
 }
 
 bar() would execute after baz();

I'm not sure about this. Of course, it would need to be illegal to declare anything within a scope(none) block. Implementing scopeless conditionals would add a runtime dependence to the ScopeStatement mechanism. The program would have to either note the value of the conditional at the time, or use some kind of function stack to keep track of which ScopeStatements will be executed. Moreover, what if it's a loop rather than an if? Should the cleanup code be executed once for each iteration of the loop, all at once when exiting the scope containing the loop? 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.
May 11 2006
prev sibling next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
I've been writing an OO binding to the cairo 2D drawing API, and
scope(success) has been a huge help.

Basically, cairo's api functions rarely if ever return an error code.
Instead, they set a flag on the object's pointer itself[1]_.  Since I
need to check this flag after every call I make on any particular
object, each wrapper class has a protected "checkStatus" member.  Then,
I just need to write this:

void someMember()
{
    scope(success) checkStatus();
    // ... do cairo stuff ...
}

When the "do cairo stuff" is just a simple function call, I don't really
gain anything.  But it comes in handy when I've got to return values
from cairo functions, or when I have to use any kind of complex logic.

Plus, I find reading "scope(success) checkStatus()" to be very clear;
that, and it's immediately obvious just looking at the code if I've
forgotten it (almost every function in the binding follows that pattern
so exceptions to that are easily spotted).

	-- Daniel

.. [1]: When I say "object" what I mean is that objects in cairo are
just pointers to undefined structs.  So a "cairo_pattern_t*" is an
"object" :P

P.S.  Cx looks very cool; must have a poke around that...

Ben Hinkle wrote:
 I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
 scope(success) and why. I can't find any reason for it.
 
 Some background: I've slowed my D work to focus on some C experimental 
 features I'm calling Cx: http://www.tinycx.org and currently I'm 
 implementing the error handling using reserved labels "error:" and 
 "finally:". The error label is roughly like scope(failure) and the finally 
 label is roughly like scope(exit). There's no try-catch-finally. I don't 
 plan on adding anything like scope(success) because I couldn't think of why 
 anyone would want to use it. Why not just put the code at the end of the 
 scope like normal code-flow? I suppose one could code the entire scope in 
 reverse just for kicks:
 void main() {
   scope(success) printf("world\n");
   scope(success) printf("hello ");
 }
 
 -Ben 
 
 

-- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 10 2006
parent Walter Bright <newshound digitalmars.com> writes:
Daniel Keep wrote:
 When the "do cairo stuff" is just a simple function call, I don't really
 gain anything.  But it comes in handy when I've got to return values
 from cairo functions, or when I have to use any kind of complex logic.
 
 Plus, I find reading "scope(success) checkStatus()" to be very clear;
 that, and it's immediately obvious just looking at the code if I've
 forgotten it (almost every function in the binding follows that pattern
 so exceptions to that are easily spotted).

Right. It eliminates the all-too-common bug of adding an extra return statement but forgetting to add the check/cleanup code that goes along with it.
May 12 2006
prev sibling next sibling parent Carlos <noone nowhere.com> writes:
Hey Ben glad to see you posting again :).  tinycx looks cool am trying 
it out.

I've never used scope(success) , so no comment really ;).

Charlie

Ben Hinkle wrote:
 I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
 scope(success) and why. I can't find any reason for it.
 
 Some background: I've slowed my D work to focus on some C experimental 
 features I'm calling Cx: http://www.tinycx.org and currently I'm 
 implementing the error handling using reserved labels "error:" and 
 "finally:". The error label is roughly like scope(failure) and the finally 
 label is roughly like scope(exit). There's no try-catch-finally. I don't 
 plan on adding anything like scope(success) because I couldn't think of why 
 anyone would want to use it. Why not just put the code at the end of the 
 scope like normal code-flow? I suppose one could code the entire scope in 
 reverse just for kicks:
 void main() {
   scope(success) printf("world\n");
   scope(success) printf("hello ");
 }
 
 -Ben 
 
 

May 11 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Ben Hinkle wrote:
 I hope this doesn't come of as a flame, but I'm wondering if anyone is using 
 scope(success) and why. I can't find any reason for it.
 
 Some background: I've slowed my D work to focus on some C experimental 
 features I'm calling Cx: http://www.tinycx.org and currently I'm 
 implementing the error handling using reserved labels "error:" and 
 "finally:". The error label is roughly like scope(failure) and the finally 
 label is roughly like scope(exit). There's no try-catch-finally. I don't 
 plan on adding anything like scope(success) because I couldn't think of why 
 anyone would want to use it. Why not just put the code at the end of the 
 scope like normal code-flow? I suppose one could code the entire scope in 
 reverse just for kicks:
 void main() {
   scope(success) printf("world\n");
   scope(success) printf("hello ");
 }

The scope(success) will execute even if the scope is exited via a return, break, or continue statement, but not if it is exited via a thrown exception. Thus, it is fundamentally different from just putting the code at the closing }. The code: { foo(); scope(success) bar(); def(); } is equivalent to: { foo(); int x; try { x = 0; def(); } catch (Object o) { x = 1; throw o; } finally { if (x == 0) bar(); } } which is a tedious, error-prone, and unobvious thing to write.
May 12 2006