DMD 0.148 - scope guard

Kyle Furlong kylefurlong at gmail.com
Sun Feb 26 10:46:51 PST 2006


James Dunne wrote:
> Kyle Furlong wrote:
>> Dawid Ciężarkiewicz wrote:
>>
>>> Dawid Ciężarkiewicz wrote:
>>>
>>>> VERSION E:
>>>> void LongFunction()
>>>> {
>>>> State save = UIElement.GetState();
>>>> onscope {
>>>>         case success: UIElement.SetState(save);
>>>>     }
>>>> onscope {
>>>>         case failure: UIElement.SetState(Failed(save));
>>>>     }
>>>> ...lots of code...
>>>> }
>>>
>>>
>>> Just came to my mind:
>>>
>>> This version is especially neat because it may be simplified to:
>>> void LongFunction()
>>> {
>>>     State save = UIElement.GetState();
>>>     onscope {
>>>         case success: UIElement.SetState(save); break;
>>>         case failure: UIElement.SetState(Failed(save));
>>>     }
>>>     ...lots of code...
>>> }
>>
>>
>> I really like this idea, cons anyone?
> 
> I don't like the words 'success' and 'failure' used all over the place. 
>  The meaning of the function's success isn't based on only if no 
> exceptions were thrown.  Similarly, the function doesn't have to 'fail' 
> if an exception were thrown.
> 
> I think they should be renamed to represent what they actually do.  That 
> is, 'no exception thrown'/'pass', 'exception thrown'/'catch', 'scope 
> exited'/'exit'.  Also, I think it would be more pleasing to the eye (and 
> the maintainer) if the effect of the scope guard were more obvious in 
> the code.  Something like:
> 
> void LongFunction()
> {
>     scope (State save = UIElement.GetState())
>     catch {
>         UIElement.SetState(Failed(save));
>     }
>     pass {
>         UIElement.SetState(save);
>     }
>     body {
>         ... lots of code ...
>     }
> }
> 
> This way, it looks like a function contract, except it applies to any 
> scope.  The catch block is reused but only for purposes of noting that 
> there was an exception caught.  The pass block is quite simply the 
> 'else' to the catch block, and should happen only if no exceptions were 
> caught.  Furthermore, there could be a general 'exit' block.
> 
> One could add as many of these blocks as necessary, and the compiler 
> will guarantee to call them in order of definition, much like the 
> original solution but not requiring one to think backwards.
> 
> bool LongFunction()
> {
>     bool  passed = false;
> 
>     scope (State save = UIElement.GetState())
>     catch { UIElement.SetState(Failed(save)); writef('0'); }
>     pass { UIElement.SetState(save); writef('1'); }
>     pass { passed = true; writef('2'); }
>     body {
>         ... lots of code ...
>     }
>     exit { writef('3'); }
> 
>     return passed;
> }
> 
> So, if an exception were thrown in '... lots of code ...', you'd see 
> '03' and the function would return false.  However, if no exception were 
> thrown you'd see '123' and the function would return true.  This 
> demonstrates the order of execution across multiple blocks.  In this 
> example, the order of the 'exit' block relative to the 'catch' and 
> 'pass' blocks is important.
> 
> Consequently, I don't think the order of the 'body' block should matter 
> at all, relative to the other blocks; and it should be fixed to only 
> allow one instance of it.  Then, it is a matter of personal/project 
> style where the 'body' block would fall.
> 
> Thoughts on this?
> 
> One last thought I had was to remove the parenthesized expression form 
> of scope (expr) ... and use another block name to represent the 
> initialization stage, just to be consistent.
> 
I think this syntax is a bit to busy for my taste. I think that it might work better as a more general proposal:

for any scope:

in
{
}
out
{
}
failure
{
}
success
{
}
body
{
}

Pros: fits into and expands current language structures
Cons: still a bit verbose as compared to current syntax



More information about the Digitalmars-d mailing list