On Fri, 21 Jan 2011 08:18:15 -0500, tamir <tamir....@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

Reply via email to