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