Thread overview
The scope of scope(exit)
Mar 10, 2006
Derek Parnell
Mar 10, 2006
Derek Parnell
Mar 10, 2006
James Dunne
Mar 10, 2006
Hasan Aljudy
Mar 10, 2006
Walter Bright
Mar 10, 2006
Hasan Aljudy
Mar 10, 2006
Sean Kelly
March 10, 2006
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
March 10, 2006
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
March 10, 2006
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
March 10, 2006
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.
March 10, 2006
"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.


March 10, 2006
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?
March 10, 2006
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