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 ourgiven
block. The changes to$_
are not visible outside of thegiven
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 thegiven
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! Usinglast
allows us to break out of ourwhile
loop, ending the game. when ($_ < $secret)
andwhen ($_ > $secret)
- These final two tests are simple comparisons. Remember that
$_
contains the item we weregiven
.
We've usedcontinue
for these statements to say that Perl should not break out of ourgiven
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.
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