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