Skip to content
Pragmas, Tied Variables, and Effective Perl
step 1/5

Reading — step 1 of 5

Learn

~3 min readIdiomatic and Metaprogramming Perl

To level up: read Effective Perl Programming (Hall, McAdams, foy) and Modern Perl (Chromatic). Both are free online. The patterns below come straight from those books.

Item 1: Always use strict; use warnings; — non-negotiable in production code.

Item 2: Default to lexical scopemy not our not implicit globals. my is the most narrowly scoped, fastest, and safest. Use our only when you genuinely need package-wide access.

Item 3: Use the right comparison. Numeric: ==, !=, <, >, <=>. String: eq, ne, lt, gt, cmp. Mixing them silently does what you didn't want.

Item 4: Choose hash slices over loops.

# Loop-y
my %colors;
for my $name (qw(red green blue)) {
    $colors{$name} = lookup($name);
}

# Slice — Perl-idiomatic
my @names = qw(red green blue);
my @values = map { lookup($_) } @names;
my %colors;
@colors{@names} = @values;     # hash slice assignment

Item 5: Use //= and ||= for defaults.

$count //= 0;       # set to 0 if undef
$name  ||= 'Anon';   # set to 'Anon' if false (undef, 0, "")

//= is safer (only checks defined-ness). ||= will overwrite 0 with the default — sometimes a bug.

Item 6: Prefer qw() for word lists.

my @opts = qw(verbose quiet help version);   # cleaner than ('verbose', 'quiet', ...)

Item 7: Use local for special variable changes.

{
    local $/ = "";       # paragraph mode (input record separator)
    while (my $para = <$fh>) { ... }
}     # $/ restored on scope exit

local is dynamic scope — applies to called subroutines too. my is lexical — only the current block.

Item 8: Tied variables — magic accessors.

tie lets you intercept access to a variable. Common: tie %hash, 'DB_File', 'data.db' — the hash is backed by a Berkeley DB file.

package CounterScalar;
sub TIESCALAR { my $class = shift; bless { count => 0 }, $class }
sub FETCH { my $self = shift; $self->{count}++; return $self->{count}; }
sub STORE { warn "can't write" }

package main;
use strict; use warnings;
our $counter;
tie $counter, 'CounterScalar';
print "$counter\n";   # 1
print "$counter\n";   # 2
print "$counter\n";   # 3

Reading $counter triggers FETCH. Most users never write tie directly — they use Tie::IxHash, DB_File, etc.

Item 9: Use Carp::croak from libraries, not die.

die reports the line where it ran. croak reports the caller's line — much more useful for users of your library.

use Carp qw(croak);
sub validate_email {
    my ($email) = @_;
    croak "invalid email: $email" unless $email =~ /\@/;
}

Item 10: Profile before optimizing. Devel::NYTProf is the gold standard. Common findings:

  • Don't qw() inside hot loops
  • \@array to avoid copying
  • Move use inside conditional code if it's only sometimes needed
  • keys %hash returns a list — for boolean test, if (%hash) is faster

Item 11: Use use 5.020; (or higher) to enable say, state, postfix dereferencing.

use 5.020;
use warnings;
use experimental 'postderef';

for my $x ($aref->@*) {        # postfix array deref
    say $x;
}

Item 12: Deprecate carefully.

Mark old code with Carp::carp warnings, list in POD, give one major-version cycle before removing. Perl culture values backward compatibility — break it sparingly.

Item 13: Read CPAN.

Whatever you're about to write, search MetaCPAN first. The idioms you discover from reading other people's code beat anything a book can teach.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…