Why we need scope(success) if I can write at the end?

Steven Schveighoffer schveiguy at yahoo.com
Fri Jan 21 07:05:30 PST 2011


On Fri, 21 Jan 2011 08:18:15 -0500, tamir <tamir.fri at gmail.com> wrote:

> or what's the differents between theese two:
> void transactionalCreate(string filename) {
>   string tempFilename = filename - ".fragment";
>   scope(success) {
>     std.file.rename(tempFilename, filename);
>   }
>   auto f = File(tempFilename, "w");
> }
> and:
> void transactionalCreate(string filename) {
>   string tempFilename = filename - ".fragment";
>   auto f = File(tempFilename, "w");
>   std.file.rename(tempFilename, filename);
> }

Look at any linux kernel driver code, and you will see goto used in a very  
structured way:

if(open_port() == -1) goto FAILURE;
if(create_device() == -1) goto FAILURE2;
if(init_device() == -1) goto FAILURE3;
return SUCCESS;
FAILURE3:
destroy_device();
FAILURE2:
close_port();
FAILURE:
return ERROR;

Basically, this idiom of building a stack of resources that must be  
destroyed in reverse order on failure is very common in a lot of code.

scope(failure) or scope(exit) takes care of these tasks without using  
gotos, and by reducing the structure required to implement such things:

open_port(); // throws exception on failure
scope(failure) close_port();
create_device();
scope(failure) destroy_device();
init_device();


Now, scope(success) I believe is less common to require, but it still has  
the benefit of allowing you to group your dealings with a certain item in  
one spot.

Imagine your code looks more like this:

void transactionalCreate(string filename) {
    string tempFilename = filename ~ ".fragment";
    auto f = File(tempFilename, "w");
    ...
    // lots of code
    ...
    std.file.rename(tempFilename, filename);
}

It might be easier to follow code that says "I'm going to create a temp  
file, and then at the end, if everything works, I'm going to copy it over  
the original" in one paragraph, rather than have to read the whole  
function to see what happens to the temp file.

It's also easier to write, you just write the scope(success) and never  
have to worry about special circumstances.

You don't have to repeat yourself if you have multiple return statements.

You can also return something from a function that may throw an exception  
without having this silly structure:

auto x = fnImGoingToReturnValueOf();
std.file.rename(tempFilename, filename);
return x;

You can just do

return fnImGoingToReturnValueOf();

and scope(success) will ensure your renaming is done properly only if that  
function doesn't throw.

-Steve


More information about the Digitalmars-d-learn mailing list