Siaris

Using a do-block
18 Oct 01 - http://www.siaris.net/index.cgi/Programming/LanguageBits/Perl/20011018.rdoc

Perl has a special kind of block called a do-block (the ‘do’ keyword followed by a block). This kind of block can be used as a term in an expression, or it can take a statement modifier.

When used as a term, the result returned is the value of the last statement evaluated in the block (rather like a subroutine’s default return value):

    my $in = do{print "Enter a number:";<STDIN>};
    print $in;

The context of the return value is the context of the expression (in the above case, since we assigned to a scalar, scalar context). The above isn’t a terribly useful example — but what about when you want to localize a global for a limited scope? Consider reading in an entire file into a scalar (inside of a larger script where you don’t want to change $/ for the duration of the script):

    my $file = 'data';
    open(FILE, $file) || die "Can't open $file: $!";
    my $contents;
    {
        local $/;   # $/ is locally undefined
        $contents = <FILE>;
    }
    print $contents;

A simpler method using a do-block might be:

    my $file = 'data';
    open(FILE, $file) || die "Can't open $file: $!";
    my $contents = do{local $/;<FILE>};
    print $contents;

With a statement modifier, this kind of block allows for a ‘run at least once’ form of the while statement:

    my $rand = int(rand(10)) + 1;
    my $guess;
    do{
        print "Enter your guess: ";
        $guess = <STDIN>;
    } while $guess != $rand;
    print "Yes: the number is $guess";

This allows us to use what looks like an uninitialized value in the conditional — it works only because the condition is tested after each block (by which time the $guess variable has a value).

The do block is also convenient for switch or case like statement blocks:

    my $rand = int(rand(10)) + 1;
    {
        print "Enter your guess: ";
        chomp(my $guess = <STDIN>);
        $guess < $rand && do{print "Too low\n"; redo};
        $guess > $rand && do{print "Too high\n";redo};
    }
    print "You guessed it!\n";

These case like examples could easily be solved using other means (like standard if/else statements), this is just another example of TMTOWTDI (there’s more than one way to do it).

*****