Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are some elegant features or uses of Perl?

Tags:

perl

People also ask

What are the uses of Perl?

Perl is a general-purpose programming language originally developed for text manipulation and now used for a wide range of tasks including system administration, web development, network programming, GUI development, and more.

What makes Perl a good language?

#1 Perl is best suited for Text Manipulation In fact, Perl has been the goto language for regex, HTML parsing, JSON manipulation, etc for almost three decades. Quite simply, no other programming language provides more powerful or easy-to-use ways of manipulating text.

Where is Perl mostly used?

Perl is popular among programmers, along with other programming languages like PHP and Python. In earlier days, programmers used Perl to write CGI scripts. Perl is often used as a departmental glue between multiple systems that are not homogenous or allowed to interoperate seamlessly.


Perl facilitates the use of lists/hashes to implement named parameters, which I consider very elegant and a tremendous aid to self-documenting code.

my $result = $obj->method(
    flux_capacitance       => 23,
    general_state          => 'confusion',
    attitude_flags         => ATTITUDE_PLEASANT | ATTITUDE_HELPFUL,
);

My favourite pieces of elegant Perl code aren't necessarily elegant at all. They're meta-elegant, and allow you to get rid of all those bad habits that many Perl developers have slipped into. It would take me hours or days to show them all in the detail they deserve, but as a short list they include:

  • autobox, which turns Perl's primitives into first-class objects.
  • autodie, which causes built-ins to throw exceptions on failure (removing most needs for the or die... construct). See also my autodie blog and video).
  • Moose, which provide an elegant, extensible, and correct way of writing classes in Perl.
  • MooseX::Declare, which provides syntaxic aweseomeness when using Moose.
  • Perl::Critic, your personal, automatic, extensible and knowledgeable code reviewer. See also this Perl-tip.
  • Devel::NYTProf, which provides me the most detailed and usable profiling information I've seen in any programming language. See also Tim Bunce's Blog.
  • PAR, the Perl Archiver, for bundling distributions and even turning whole programs into stand-alone executable files. See also this Perl-tip.
  • Perl 5.10, which provides some stunning regexp improvements, smart-match, the switch statement, defined-or, and state variables.
  • Padre, the only Perl editor that integrates the best bits of the above, is cross-platform, and is completely free and open source.

If you're too lazy to follow links, I recently did a talk at Linux.conf.au about most of the above. If you missed it, there's a video of it on-line (ogg theora). If you're too lazy to watch videos, I'm doing a greatly expanded version of the talk as a tutorial at OSCON this year (entitled doing Perl right).

All the best,

Paul


I'm surprised no one mentioned the Schwartzian Transform.

my @sorted =
  map  { $_->[0] }
  sort { $a->[1] <=> $b->[1] }
  map  { [ $_, expensive_func($_) ] }
@elements;

And in the absence of a slurp operator,

my $file = do { local $/; readline $fh };

Have a list of files the user wants your program to process? Don't want to accidentally process a program, folder, or nonexistent file? Try this:

@files = grep { -T } @files;

And, like magic, you've weeded out all the inappropriate entries. Don't want to ignore them silently? Add this line before the last one:

warn "Not a file: $_" foreach grep { !-T } @files;

Prints a nice warning message for every file that it can't process to standard error. The same thing without using grep would look like this:

my @good;
foreach(@files) {
  if(-T) {
    push @good, $_;
  } else {
    warn "Not a file: $_";
  }
}

grep (and map) can be used to make code shorter while still keeping it very readable.


The "or die" construct:

open my $fh, "<", $filename
    or die "could not open $filename: $!";

The use of qr// to create grammars:

#!/usr/local/ActivePerl-5.10/bin/perl

use strict;
use warnings;
use feature ':5.10';

my $non_zero         = qr{[1-9]};
my $zero             = qr{0};
my $decimal          = qr{[.]};
my $digit            = qr{$non_zero+ | $zero}x;
my $non_zero_natural = qr{$non_zero+ $digit*}x;
my $natural          = qr{$non_zero_natural | $zero}x;
my $integer          = qr{-? $non_zero_natural | $zero}x;
my $real             = qr{$integer (?: $decimal $digit)?}x;

my %number_types = (
    natural => qr/^$natural$/,
    integer => qr/^$integer$/,
    real    => qr/^$real$/
);

for my $n (0, 3.14, -5, 300, "4ever", "-0", "1.2.3") {
    my @types = grep { $n =~ $number_types{$_} } keys %number_types;
    if (@types) {
        say "$n is of type", @types == 1 ? " ": "s ", "@types";
    } else {
        say "$n is not a number";
    }
}

Anonymous subroutines used to factor out duplicate code:

my $body = sub {
    #some amount of work
};

$body->();
$body->() while $continue;

instead of

#some amount of work
while ($continue) {
    #some amount of work again
}

Hash based dispatch tables:

my %dispatch = (
    foo => \&foo,
    bar => \&bar,
    baz => \&baz
);

while (my $name = iterator()) {
    die "$name not implemented" unless exists $dispatch{$name};
    $dispatch{$name}->();
}

instead of

while (my $name = iterator()) {
    if ($name eq "foo") {
        foo();
    } elsif ($name eq "bar") {
        bar();
    } elsif ($name eq "baz") {
        baz();
    } else {
        die "$name not implemented";
    }
}

Three-line classes with constructors, getter/setters and type validation:

{
    package Point;
    use Moose;

    has ['x', 'y'] => (isa => 'Num', is => 'rw');
}

package main;
my $point = Point->new( x => '8', y => '9' );

$point->x(25);