Idiomatic Perl





Idiomatic Perl

Perl is a language designed by a linguist, and as much as any human language, Perl is a language of idioms.

What I call idiomatic Perl is the mixture of elegance and custom that comes naturally to Perl programmers, or, at least hopefully, to the majority of them, after experience and experimentation. Exactly what is idiomatic and what is purely a matter of style or opinion is debatable. There are many different ways to express both simple and complex algorithms in Perl. Some ways, however, are clearly more "right" than others.

Perl is hardly ever a programmer's first language. Newly minted Perl programmers are usually familiar with the C programming language, or shell scripting, or both. They may also be familiar with other languages. Because Perl derives much of its distinctive syntax and functionality from other well-known languages, the first temptation of a beginning programmer is to write Perl in a way that resembles something from a familiar environment:

$n = $#ary; 
for ($i = 0; $i <= $n; $i++) { 
  $sum += $ary[$i]; 
}

Add up all the elements of @ary using subscripts—as in C.

Or, perhaps:

while ($val = shift @ary) { 
  $sum += $val; 
}

Add up all the elements of @ary—a shell-ish approach that leaves @ary empty.

Both of the above will work, but neither is particularly succinct or efficient. The subscripting operation in the first example is slow and unneces-sary, and the second version leaves @ary empty, which may not be desirable. The idiomatic way is:

foreach (@ary) { 
  $sum += $_; 
}

Add up all the elements of @ary—the Perl way.

Idiom and convention are very important in Perl. They are less important in simple languages like C and Bourne or C shell. There are not too many tricks to be learned in C programming. (You may think I'm crazy to say that, but if you take a look at your local bookstore's programming section, you will see that all the books on how to do clever things in C are fairly skinny. It's the books on C++ that are thick.) And although there are a lot of details to be learned in support of shell programming, a thorough how-to book on shell programming is a slim volume.

Not so with Perl.

Perl is an expressive language and often a succinct one. The language has been designed to allow frequently used constructs to be coded very compactly. Perl's very high level features like <>, regular expressions, and grep are particularly potent. For example:

($a, $b) = ($b, $a);

Swap $a and $b.

print sort <>;

Read lines from files or standard input and print them out in sorted order.

print grep /\bjoebloe\b/, <>;

Print all the lines containing the word joebloe.

@div5 = grep { not $_ % 5 } @n;

Copy all the numbers in @n evenly divisible by 5 into @div5.

$bin_addr = pack 'C4', 
  split /\./, $str_addr;

One way of turning "123.234.0.1" into the integer 0x7bea0001.

All of these examples can be coded in other ways, but when written in the style of some other language, the result will be longer and less efficient. You could, say, reproduce the functionality of <> explicitly in Perl, but the result would be a fairly long Perl program that would obscure the "interesting" part of the program. The resulting program would also be harder to debug and to maintain, simply because of its greater length and complexity.

To a certain extent, idiom and style overlap. Some idioms, like print sort <>, are inarguable, but there are certainly gray areas:

foreach $key (sort keys %h) { 
  print "$key: $h{$key}\n"; 
}

Print key-value pairs from %h one per line.

print map "$_: $h{$_}\n", 
  sort keys %h;

Another way to print key-value pairs.

The first example above is very plain Perl. It is efficient and readable and uses only basic features of the language. The second example is shorter and, some might argue, has a higher "cool factor" because it uses the nifty map operator and a list context in place of the mundane foreach loop in the first. However, you should consider yourself and your potential audience before leaving code like the second example for posterity, because it is definitely more obscure (but not that obscure) and might even be less efficient.

Every Perl programmer needs to master a number of basic idioms and should at least learn to recognize a number of others. Programmers should always use those idioms that produce efficient, succinct, and readable code. Other more complex idioms may or may not be appropriate, depending on the programmer, audience, and nature of the program being written.

In this section (were you wondering when it would ever really get started?), we'll look at a number of Perl idioms. You will definitely want to learn and use the simpler ones. Beyond that, you will have to consider the trade-offs between "plain" and "nifty."

How your Perl looks is up to you. You can write very plain Perl if you like. Writing plain Perl is like building a house and choosing to build as much as possible out of masonry blocks. It works, it's simple, it's a little dull, and it's hard to create intricate shapes.

On the other hand, you may want to try using all the nifty features that Perl gives you. Continuing the analogy, you may be the kind of builder who spends more time at Home Depot looking at power tools than he does pounding nails on the job. You may like to build all kinds of cool features using the latest technology. This is fine, so long as you realize that sometimes a hammer is all you need.

Or, maybe after a while you will wind up somewhere in between.

Sometimes you need s/\G0/ /g, [1] and sometimes you just need $a = $b.

[1] This little jewel is discussed in Item 60.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows