Perl switch Statement

Until 5.10 version Perl has no switch statement to implement a case mechanism in order to avoid the if-elsif-else pattern, but it is easy to build one. Perl 5.10 comes with a built-in switch but it will be spelled "given".

The switch statement found in other languages is very useful when you have a multiway branch statement or some case structures.

In Perl you can easily emulate this statement using different techniques or you can use the Perl given/when statements starting with the 5.10 Perl version (the keywords given and when are analogous to Perl switch and case from other languages).

Or you can use the Switch module found at CPAN.

You can use a bare block and the && operator in order to construct a case structure that looks syntactically similar with the switch statement found in other languages. You can label your block with the noun SWITCH and because a bare block is a loop that executes only once, you can use the last, next and redo loop controls inside.

Your compound Perl switch statement could look as follows:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $var = 2;
SWITCH: {
  $var == 1 && do { print "\$var=1\n"; last SWITCH; };
  $var == 2 && do { print "\$var=2\n"; last SWITCH; };
  $var == 3 && do { print "\$var=3\n"; last SWITCH; };
  print "\$var is not equal with 1 or 2 or 3\n";
}
# the output displays $var = 2
In the syntax form used above, you can omit even the label SWITCH.

The last control will immediately end the execution of the block and will jump at the following statement after the block (labeled or not).

Please note that the last control ignores the do block which is not a loop and exits from the SWITCH block instead.

Inside the Perl switch block, on each line the $var is first evaluated and if the left condition is true, the script will execute the corresponding do block.

You can use a hash structure to emulate a switch statement, as in the following example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
# initialize some hash structure
my %fruitsColors = (
  "apple" => "red",
  "banana" => "yellow",
  "orange" => "orange",
  "plum" => "dark-blue"
);
 
print "Fruit: ";
while (my $fruit = <STDIN>) {
  chomp $fruit;
  my $color = $fruitsColors {lc $fruit} || "unknown";
  print "The $fruit has the colour $color\n";
  print "Fruit: ";
}
In this way, the string lookup runs very fast. We use a while block to read a few lines from STDIN, until the EOF is met (typing Ctrl/z in Windows or Ctrl/d in Linux). Inside the while block:
 
  • the word read from STDIN is stored in the scalar variable $fruit
  • we discard the trailing newline of the word (by applying the built-in chomp function)
  • next, we look up in the %fruitsColors hash for the fruit name and if we find it, we store the given color of the fruit in the $color scalar variable, otherwise the $color variable will be initialized with the text "unknown"
  • finally, the result of the search will be printed

In the hash structure you can use an unlimited number of entries, the disadvantage of this method is that you can’t search for a match, but only for a specific entry item (like apple, banana, and so on).

You must also keep in mind that if the hashtable is too big, Perl will allocate a lot of memory to store its (key, value) pair elements.

You can emulate the Perl switch statement using the corresponding form of if as a modifier, inside a while loop:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $color;
 
print "Gess the colours:\n";
 
LINE: while(<STDIN>) {
  SWITCH: {
    $color = "blue", last SWITCH if /blue/i;
    $color = "white", last SWITCH if /white/i;
    $color = "red", last SWITCH if /red/i;
    print "Try again\n"; next LINE;
  }
  print "color = $color\n";
}
This code will read a line of text from the standard input stream and if one of the words (blue, white or red) matches, it will display the word; otherwise it will display the text "Try again " and the script program will continue by reading another line of text.

Please note the using of the case insensitively regex match operator here (/i modifier).

This module was made available beginning with the 5.8.x version of Perl and covers a lot of possible combinations of Perl switch having as single input argument (in a scalar context) a number, a string, a specific pattern, a reference to an array or a hash (associative array), or a call to a subroutine.

Like the switch from the C language, the Switch module allows you the use of fall-through – i.e. trying another case after one that has already succeeded.

Now this module was included in the Perl core distribution, but if you have an older version of Perl it’s possible that this module is not included (in this case if you want to use the Switch module you need to install it - on a Windows platform, if you installed ActiveState’s ActivePerl, you can run their Perl Package Manager from your command shell - or upgrade your Perl version).

For a full description of all its features, you can locate this module by searching at CPAN after the word 'switch' and learn more ways to invoke it.

The next simple script sample shows you one of the way through which you can use the Switch module in your Perl programs or applications:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
use Switch;
 
my $i;
chomp(my $var=<STDIN>);
 
switch ($var){
  case(1) { $i="One"; }
  case(2) { $i="Two"; }
  case(3) { $i="Three"; }
  else    { $i="Other"; }
}
 
print "case: $i\n";
You can mix both switch/given formats if you use the declaration:
use Switch 'Perl5', 'Perl6';

Based on the Perl 6 proposal, starting from Perl 5.10 is enabled a new switch feature. This Perl switch statement is spelled given, and case is pronounced when.

The using of the Perl given/when statement is very similar (there are minor differences) with the Perl switch/case statement.

For instance, see the following example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($var, $i) = 2;
 
given ($var){
  when(1) { $i='One'; }
  when(2) { $i='Two'; }
  when(3) { $i='Three'; }
  default { $i='Other'; }
}
 
print "when: $i\n";