Reading — step 1 of 5
Learn
Long if/elsif chains are an anti-pattern in any language. In Perl, the idiomatic replacement is a dispatch table — a hash whose values are coderefs.
Basic dispatch table:
use strict; use warnings;
my %ops = (
add => sub { $_[0] + $_[1] },
sub => sub { $_[0] - $_[1] },
mul => sub { $_[0] * $_[1] },
div => sub { $_[1] != 0 ? $_[0] / $_[1] : die "div zero" },
);
my ($op, $a, $b) = ('add', 3, 4);
my $result = $ops{$op}->($a, $b);
print "$result\n"; # 7
Hash lookup is O(1). The structure is data, not control flow — easy to extend at runtime.
Command parser — common in CLIs and protocol handlers:
my %commands = (
help => \&do_help,
version => \&do_version,
list => \&do_list,
add => \&do_add,
);
my ($cmd, @args) = @ARGV;
$commands{$cmd} ? $commands{$cmd}->(@args) : usage();
Adding a new command = adding a hash entry. No if/elsif maintenance.
Method dispatch on data attribute:
sub handle {
my ($event) = @_;
my %handler = (
login => sub { ... },
logout => sub { ... },
click => sub { ... },
);
if (my $h = $handler{$event->{type}}) {
return $h->($event);
}
warn "unknown event type: $event->{type}";
}
Closures inside dispatch tables — shared state:
sub make_calculator {
my $value = 0;
return {
add => sub { $value += $_[0] },
reset => sub { $value = 0 },
get => sub { $value },
};
}
my $calc = make_calculator();
$calc->{add}->(10);
$calc->{add}->(5);
print $calc->{get}->(), "\n"; # 15
This is the Perl version of an object — without bless. Sometimes nicer because the interface is just a hash; very transparent.
map / grep / sort are first-class FP:
use List::Util qw(reduce);
my @nums = (1, 2, 3, 4, 5);
my $sum_squares = reduce { $a + $b } map { $_ ** 2 } @nums;
my @evens_doubled = map { $_ * 2 } grep { $_ % 2 == 0 } @nums;
Note: in reduce, $a and $b are accumulator and current item.
Schwartzian transform — Perl's classic decorate-sort-undecorate idiom for expensive sort keys:
# sort filenames by mtime, expensive to call -M repeatedly
my @sorted = map { $_->[1] } # 3. extract original
sort { $a->[0] <=> $b->[0] } # 2. sort by precomputed
map { [-M $_, $_] } # 1. decorate with key
@files;
Read bottom-up: decorate, sort, undecorate. Each -M runs once per file instead of N log N times.
Composition with closures:
sub compose {
my @fns = @_;
return sub {
my @args = @_;
for my $f (reverse @fns) {
@args = $f->(@args);
}
return wantarray ? @args : $args[0];
};
}
my $f = compose(
sub { $_[0] + 1 },
sub { $_[0] * 2 },
);
print $f->(5); # (5*2)+1 = 11
Functional patterns blend smoothly with Perl's procedural roots — use them where they make code clearer.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…