Siaris
Simple Things
Syndicate: full/short
Siaris
Categories
General0
News2
Programming2
LanguageBits0
Perl50
Ruby10
VersionControl1
Misc1
Article Calendar
<= May, 2008
S M T W T F S
123
45678910
11121314151617
18192021222324
25262728293031
Search this blog

Key links
External Blogs
Brought to you by ...
Ruby
1and1.com

Using a do-block

Andrew L. Johnson (First published by ItWorld.com 2001-10-18)

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).

*****