Perl borrows from many languages. One consequence of this is that it is easy for programmers to learn: it probably supports some features of languages that they already know. On the other hand, Perl also has powerful constructs that aren't found in other languages.
This page describes some Perl idioms that may not be obvious to programmers coming from other languages.
%humped = { camel => 1, dromedary => 1 };The elements of the set (keys of the hash) are guaranteed unique. To test whether an element is in the set, write
$humped{$animal} or die "$animal has no humps\n";
for
, while
, and until
.
It also provides two implicit looping constructs:
map
and grep
.
Explicit loops are preferred when the loop body is executed for its side effects:
foreach $animal (@animals) { print "$animal\n" }Implicit loops are preferred when the loop body is executed for its value:
@humped = grep { $humped{$_} } @animals;Combining
map
with the hash construct described
above yields the unique elements of a list:
%unique = map { $_ => 1 } @list; @unique = keys %unique;Be agressive with
map
.
Any time you see
for (@a) { push @b, ... }consider replacing it with
@b = map { ... } @a;
if (expression) { statement } elsif (expression) { statement } else { statement }It also has statement-oriented control structures:
statement if expression; statement unless expression;and expression-oriented control structures:
expression and expression; expression or expression;Any time you find yourself using
if
to control a block of code,
consider whether you couldn't do the same thing more simply using
and
or or
to control an expression:
if (open(FOO, "foo") { ... } else { die Can't open "foo: $!\n"; }becomes
open(FOO, "foo") or die "Can't open foo: $!\n";
for
as switch$_
.
The for
loop will do this assignment,
and provide a block for the cases to exit from, as well:
for ($animal) { /camel/ and do Humps(2), last; /dromedary/ and do Humps(1), last; }
$val = $object->method->[3]but using the same reference in a
for
loop is awkward:
for (@{$object->method})If a class itself doesn't dictate one approach or the other on conceptual grounds, let the user choose:
sub method { ... wantarray ? @array : \@array }Then the
for
loop becomes
for ($object->method)while a user who cares about efficiency can still write
$arrayref = $object->method;
Getopt::Std
to parse command line flags.
You can set default values by assigning to the %Options
hash before calling getopt()
:
$Options{c} = 'blue'; getopt('c', \%Options); $color = $Options{c};
undef $/
.
undef $/; $everything = <FH>However, all filehandles use the same value of
$/
,
so you have to restore its previous value afterwards,
or risk problems with other files.
If you localize $/
inside a block
(or a subroutine), then its previous value is automatically
restored when you exit the block.
{ local $/; undef $/; $everything = <FH1> } $something = <FH2>
Alternately, you can join all the lines on null:
$everything = join('', <FH>);For a list of all the words in a files, write:
@words = split(' ', join('' <FH>));