Is there a way to replace an if-elsif-else in Perl with something better?
A couple of people have mentioned a dispatch table. There are two things and it's nice to keep them apart sometimes. There's the list of possible things that could happen, and the thing that makes them happen. If you couple the two, you're stuck with your solution. If you keep them separate, you have more flexibility later.
The dispatch table specifies the behavior as data instead of program structure. Here's two different ways to do it. With your example you have integers and something like that might use an array to store things. The hash example is the same idea but looks up the behavior slightly differently.
Also notice that I factor out the print
. When you have repeated code like that, try to move the repeated stuff up a level.
use v5.10;
foreach my $factor ( map { int rand 5 } 0 .. 9 ) {
say get_age_array( $factor );
}
my @animals = qw( cat dog bird frog );
foreach my $factor ( map { $animals[ rand @animals ] } 0 .. 9 ) {
say get_age_hash( $factor );
}
sub get_age_array {
my $factor = shift;
state $dispatch = [
sub { 'Nothing!' }, # index 0
sub { "Calling 1" },
sub { 1 + 1 },
sub { "Called 3" },
sub { time },
];
return unless int $factor <= $#$dispatch;
$dispatch->[$factor]->();
}
sub get_age_hash {
my $factor = shift;
state $dispatch = {
'cat' => sub { "Called cat" },
'dog' => sub { "Calling 1" },
'bird' => sub { "Calling 2, with extra" },
};
return unless exists $dispatch->{$factor};
$dispatch->{$factor}->();
}
Update: Make sure you read brian's comment below; basically, it's better to use for
instead of given
, due to various issues he comments on in his link. I've updated my advice to incorporate his improvements, which he outlines in Use for() instead of given():
If you're on perl 5.10 or newer, given/when
is the magic pair you are looking for, but you really should use for/when
instead.. Here's an example:
use strict;
use warnings;
use feature qw(switch say);
print 'Enter your grade: ';
chomp( my $grade = <> );
for ($grade) {
when ('A') { say 'Well done!' }
when ('B') { say 'Try harder!' }
when ('C') { say 'You need help!!!' }
default { say 'You are just making it up!' }
}