Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtain a switch/case behaviour in Perl 5

Is there a neat way of making a case or switch statement in Perl 5?. It seems to me they should include a switch on version 6..

I need this control structure in a script, and I've heard you can import a "switch module". But how can I achieve it without imports to minimize dependencies and acquire portability?

like image 662
lurks Avatar asked May 10 '09 03:05

lurks


People also ask

Does Perl have a switch statement?

Perl does not support the use of switch statements. A switch statement allows a variable to be tested against a set list of values.

What is switch case explain with example?

Switch Case Example in CA switch construct is used to compare the value stored in variable num and execute the block of statements associated with the matched case. In this program, since the value stored in variable num is eight, a switch will execute the case whose case-label is 8.

What is the syntax of switch case?

The syntax of the switch statement is: statement(s); break; case constant 2: statement(s);


4 Answers

If you are using Perl 5.10 you have given/when which is a switch statement (note, it can do more than compare with regexes, read the linked docs to see its full potential):

#or any of the dozen other ways to tell 5.10 to use its new features
use feature qw/switch/; 

given($string) {
    when (/^abc/) { $abc     = 1; }
    when (/^def/) { $def     = 1; }
    when (/^xyz/) { $xyz     = 1; }
    default       { $nothing = 1; }
}

If you are using Perl 5.8 or earlier you must make do with if/elsif/else statements:

if    ($string =~ /^abc/) { $abc     = 1; }
elsif ($string =~ /^def/) { $def     = 1; }
elsif ($string =~ /^zyz/) { $xyz     = 1; }
else                      { $nothing = 1; }

or nested condition operators (?:):

$string =~ /^abc/ ? $abc     = 1  :
$string =~ /^def/ ? $def     = 1  :
$string =~ /^xyz/ ? $xyz     = 1  :
                    $nothing = 1;

There is a module in Core Perl (Switch) that gives you fake switch statements via source filters, but it is my understanding that it is fragile:

use Switch;

switch ($string) {
    case /^abc/ {
    case /^abc/ { $abc     = 1 }
    case /^def/ { $def     = 1 }
    case /^xyz/ { $xyz     = 1 } 
    else        { $nothing = 1 }
}

or the alternate syntax

use Switch 'Perl6';

given ($string) {  
    when /^abc/ { $abc     = 1; }
    when /^def/ { $def     = 1; }
    when /^xyz/ { $xyz     = 1; }
    default     { $nothing = 1; }
}
like image 192
Chas. Owens Avatar answered Oct 17 '22 15:10

Chas. Owens


The suggestion in Programming Perl is:


for ($string) {
    /abc/ and do {$abc    = 1; last;};
    /def/ and do {$def    = 1; last;};
    /xyz/ and do {$xyz    = 1; last;};
    $nothing = 1;
}
like image 25
Nathan Fellman Avatar answered Oct 17 '22 13:10

Nathan Fellman


Just a short comment about the core Switch module that's been mentioned a couple of times in answers. The module in question relies on source filters. Among other things, that may result in wrong lines reported for errors. It's so bad that none of the core developers really remembers or cares to remember why it was accepted into the perl core in the first place.

Furthermore, Switch.pm will be the first Perl module ever to be removed from the perl core. The next major release of perl, 5.12.0, will still have it, albeit with a deprecation warning. That deprecation warning will go away if you explicitly install Switch.pm from CPAN. (You get what you ask for.) In the next release down the road, 5.14, Switch.pm will be entirely removed from core.

like image 11
tsee Avatar answered Oct 17 '22 13:10

tsee


An equivalent solution that I like is a dispatch table.

my $switch = {
  'case1' => sub { print "case1"; },
  'case2' => sub { print "case2"; },
  'default' => sub { print "unrecognized"; }
};
$switch->{$case} ? $switch->{$case}->() : $switch->{'default'}->();
like image 9
jiggy Avatar answered Oct 17 '22 15:10

jiggy