[ Perl tips index ]
[ Subscribe to Perl tips ]
Perl 5.10 introduces a native switch statement into the language. Like
other features in Perl 5.10, we can enable it with the use feature
pragma.
use feature qw(switch);
It's also possible to enable all Perl 5.10 features with any of the following:
use feature qw(:5.10);
use 5.10.0; # Requires perl v5.10.0 or later.
use 5.010; # Same, with nicer errors on older versions.
Perl's new switch feature is best demonstrated with an example.
Let's take the classic guessing game, where the computer picks a number
and our user needs to try and guess it.
use strict;
use warnings;
use feature qw(switch say);
# Pick our random number between 1 and 100
my $secret = int(rand 100)+1;
# An array of numbers guessed thus far
my @guessed;
say "Guess my number between 1-100";
# Get each guess from the user
while (my $guess = <STDIN>) {
chomp $guess;
# Check their guess using given/when
given($guess) {
when (/\D/) { say "Give me an integer"; }
when (@guessed) { say "You've tried that"; }
when ($secret) { say "Just right!"; last; }
when ($_ < $secret) { say "Too low"; continue; }
when ($_ > $secret) { say "Too high"; continue; }
# record the guess they've made
push(@guessed,$_);
}
}
The heart of our program is the given/when block, which is
enabled by the use of use feature qw(switch) at the top of our code.
Let's look at each part in detail:
given($guess)A given construct marks the start of our switch logic. It
has the effect as assigning $_ to $guess for the duration
of our given block. The changes to $_ are not visible outside
of the given block (ie, they are lexical in scope).
when (/\D/)when provided with a regular expression checks to see if $_
matches that regular expression. In our case, if our input
contains non-digit characters, then we have something that doesn't
look like an integer, and execute the associated block.
After a successful when match Perl will automatically break out of the
given block unless told otherwise. In our case this repeats the loop asking
the user for another guess.
when (@guessed)In this second test we're asking whether $guess appears as a value in
the @guessed. If it does we inform the user and go onto their next
guess.
when ($secret)This is a direct comparison. Is $guess the same value as $secret?.
If so the player has guessed correctly! Using last allows us to break
out of our while loop, ending the game.
when ($_ < $secret) and when ($_ >
$secret)These final two tests are simple comparisons. Remember that $_ contains
the item we were given.
We've used continue for these statements to say that Perl should
not break out of our given block on a successful match. This
means that if the user guesses too low or too high, we will eventually
evaluate the line:
push(@guesses,$guess);
which remembers the guess as one we've already seen.
You can also use when with hashes (is $_ a key in the hash),
subroutines (does the subroutine return true with $_ as an argument)
and strings (tests for string equality). Furthermore, our
given expression need not be merely a number or a string, we can also
compare arrays, and hashes if we want to.
Finally, we can also set a default case, for when nothing has matched, although we have not shown it in our example.
If you've enabled use feature qw(switch then you can also use
a foreach/when construct. Here's an example of tallying up
the number of times we see cool things in a list:
use feature qw(switch);
foreach (@cool_things) {
when (/pirate/) { $pirate++ }
when (/ninja/) { $ninja++ }
when (/robot/) { $robot++ }
say "$_ doesn't look cool...";
}
If a when is activated, it automatically goes onto the next
iteration of the foreach loop. Just like given/while, we can
use the continue keyword to continue examining later options after
a successful match.
It should be noted that foreach/when only works when using Perl's
default $_ variable for iteration.
In Perl 5.10 we can write:
my $_;
This is allows us to do anything we like with $_, but without the
possibility of changing $_ for code outside our current block. It's
strongly recommended for subroutines using $_ in Perl 5.10 to
avoid accidentally changing $_ for your caller.
For further information, we recommend the following resources:
[ Perl tips index ]
[ Subscribe to Perl tips ]
This Perl tip and associated text is copyright Perl Training Australia. You may freely distribute this text so long as it is distributed in full with this Copyright noticed attached.
If you have any questions please don't hesitate to contact us:
| Email: | contact@perltraining.com.au |
| Phone: | 03 9354 6001 (Australia) |
| International: | +61 3 9354 6001 |
Copyright Perl Training Australia. Contact us at contact@perltraining.com.au