www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - The scope of scope(exit)

reply Derek Parnell <derek psych.ward> writes:
The following code did not work as I expected it to.

-----------------------
import std.stdio;
int Foo(int x)
{
    int y;
    y = x;
    scope(exit) { if (x < 5) y += 9; }
    return y;
}

void main()
{
    int i;
    i = 1;
    writefln("Foo IN %s OUT %s", i, Foo(i));
    i = 7;
    writefln("Foo IN %s OUT %s", i, Foo(i));
}
------------------------

I got ...

  Foo IN 1 OUT 1
  Foo IN 7 OUT 7

but expected ...

  Foo IN 1 OUT 8
  Foo IN 7 OUT 7

It appears that the return statement is not the last thing executed in the
function. It appears that it caches the value it is about to return,
executes the scope(exit) code, then returns the cached value. Which makes
it difficult for a scope(exit) statement to effect the returned value.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
10/03/2006 12:55:29 PM
Mar 09 2006
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 10 Mar 2006 12:58:08 +1100, Derek Parnell wrote:

Oops , should have read ...

but expected ...
 
   Foo IN 1 OUT 10
   Foo IN 7 OUT 7


-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
10/03/2006 12:58:45 PM
Mar 09 2006
parent James Dunne <james.jdunne gmail.com> writes:
Derek Parnell wrote:
 On Fri, 10 Mar 2006 12:58:08 +1100, Derek Parnell wrote:
 
 Oops , should have read ...
 
 but expected ...
  
    Foo IN 1 OUT 10
    Foo IN 7 OUT 7
 
 

Putting the return in the scope(exit) block fixes the problem. Interesting, but not unexpected. I'd say this way provides more flexibility, but also may cause confusion (as it just did). -- Regards, James Dunne
Mar 09 2006
prev sibling next sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Derek Parnell wrote:
 The following code did not work as I expected it to.
 
 -----------------------
 import std.stdio;
 int Foo(int x)
 {
     int y;
     y = x;
     scope(exit) { if (x < 5) y += 9; }
     return y;
 }
 
 void main()
 {
     int i;
     i = 1;
     writefln("Foo IN %s OUT %s", i, Foo(i));
     i = 7;
     writefln("Foo IN %s OUT %s", i, Foo(i));
 }
 ------------------------
 
 I got ...
 
   Foo IN 1 OUT 1
   Foo IN 7 OUT 7
 
 but expected ...
 
   Foo IN 1 OUT 8
   Foo IN 7 OUT 7
 
 It appears that the return statement is not the last thing executed in the
 function. It appears that it caches the value it is about to return,
 executes the scope(exit) code, then returns the cached value. Which makes
 it difficult for a scope(exit) statement to effect the returned value.
 

I think the documentation should explain these situations a bit more.
Mar 09 2006
prev sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message 
news:1amv63k5pimu6.q5fyzezd5ew5.dlg 40tude.net...
 The following code did not work as I expected it to.

Think of it like: int Foo(int x) { int y; y = x; try { return y; } finally { if (x < 5) y += 9; } } which should make it clear. The reason it works this way is because the return expression can be arbitrarilly complicated, and can throw exceptions. So the exit code must be executed *after* the return value is computes.
Mar 09 2006
parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Walter Bright wrote:
 "Derek Parnell" <derek psych.ward> wrote in message 
 news:1amv63k5pimu6.q5fyzezd5ew5.dlg 40tude.net...
 
The following code did not work as I expected it to.

Think of it like: int Foo(int x) { int y; y = x; try { return y; } finally { if (x < 5) y += 9; } } which should make it clear. The reason it works this way is because the return expression can be arbitrarilly complicated, and can throw exceptions. So the exit code must be executed *after* the return value is computes.

What happens when an exception is thrown inside the scope(exit) block?
Mar 09 2006
parent Sean Kelly <sean f4.ca> writes:
Hasan Aljudy wrote:
 
 What happens when an exception is thrown inside the scope(exit) block?

The same as when an exception is thrown from a finally block: the remainder of the block is not executed and the new exception is passed up the stack in place of the old one. Sean
Mar 09 2006