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
givenconstruct marks the start of our switch logic. It has the effect as assigning$_to$guessfor the duration of ourgivenblock. The changes to$_are not visible outside of thegivenblock (ie, they are lexical in scope). when (/\D/)whenprovided 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
whenmatch Perl will automatically break out of thegivenblock 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
$guessappears 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
$guessthe same value as$secret?. If so the player has guessed correctly! Usinglastallows us to break out of ourwhileloop, ending the game. when ($_ < $secret)andwhen ($_ > $secret)- These final two tests are simple comparisons. Remember that
$_contains the item we weregiven.
We've usedcontinuefor these statements to say that Perl should not break out of ourgivenblock 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.
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.
foreach / when
If you've enableduse 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.Lexical $_
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.
No comments:
Post a Comment