Alex Rivera | Logout

Hidden features of Perl?

Asked 2008-10-02T11:49:22.907
141

What are some really useful but esoteric language features in Perl that you've actually been able to employ to do useful work?

Guidelines:

  • Try to limit answers to the Perl core and not CPAN
  • Please give an example and a short description

Hidden Features also found in other languages' Hidden Features:

(These are all from Corion's answer)

  • C
    • Duff's Device
    • Portability and Standardness
  • C#
    • Quotes for whitespace delimited lists and strings
    • Aliasable namespaces
  • Java
    • Static Initalizers
  • JavaScript
    • Functions are First Class citizens
    • Block scope and closure
    • Calling methods and accessors indirectly through a variable
  • Ruby
    • Defining methods through code
  • PHP
    • Pervasive online documentation
    • Magic methods
    • Symbolic references
  • Python
    • One line value swapping
    • Ability to replace even core functions with your own functionality

Other Hidden Features:

Operators:

  • The bool quasi-operator
  • Edit
    Report

13 Answers

47

There are many non-obvious features in Perl.

For example, did you know that there can be a space after a sigil?

 $ perl -wle 'my $x = 3; print $ x'
 3

Or that you can give subs numeric names if you use symbolic references?

$ perl -lwe '*4 = sub { print "yes" }; 4->()' 
yes

There's also the "bool" quasi operator, that return 1 for true expressions and the empty string for false:

$ perl -wle 'print !!4'
1
$ perl -wle 'print !!"0 but true"'
1
$ perl -wle 'print !!0'
(empty line)

Other interesting stuff: with use overload you can overload string literals and numbers (and for example make them BigInts or whatever).

Many of these things are actually documented somewhere, or follow logically from the documented features, but nonetheless some are not very well known.

Update: Another nice one. Below the q{...} quoting constructs were mentioned, but did you know that you can use letters as delimiters?

$ perl -Mstrict  -wle 'print q bJet another perl hacker.b'
Jet another perl hacker.

Likewise you can write regular expressions:

m xabcx
# same as m/abc/
answered 2008-10-02T12:50:58.907
22

Based on the way the "-n" and "-p" switches are implemented in Perl 5, you can write a seemingly incorrect program including }{:

ls |perl -lne 'print $_; }{ print "$. Files"'

which is converted internally to this code:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}
answered 2008-10-02T12:48:32.377
10

A bit obscure is the tilde-tilde "operator" which forces scalar context.

print ~~ localtime;

is the same as

print scalar localtime;

and different from

print localtime;
answered 2008-10-02T12:42:14.277
9

The input record separator can be set to a reference to a number to read fixed length records:

$/ = \3; print $_,"\n" while <>; # output three chars on each line
answered 2009-06-22T12:39:06.350
4

Safe compartments.

With the Safe module you can build your own sandbox-style environment using nothing but perl. You would then be able to load perl scripts into the sandbox.

Best regards,

answered 2008-10-02T18:03:06.753
4

All right. Here is another. Dynamic Scoping. It was talked about a little in a different post, but I didn't see it here on the hidden features.

Dynamic Scoping like Autovivification has a very limited amount of languages that use it. Perl and Common Lisp are the only two I know of that use Dynamic Scoping.

answered 2008-10-05T15:12:40.870
3

You can replace the delimiter in regexes and strings with just about anything else. This is particularly useful for "leaning toothpick syndrome", exemplified here:

$url =~ /http:\/\/www\.stackoverflow\.com\//;

You can eliminate most of the back-whacking by changing the delimiter. /bar/ is shorthand for m/bar/ which is the same as m!bar!.

$url =~ m!http://www\.stackoverflow\.com/!;

You can even use balanced delimiters like {} and []. I personally love these. q{foo} is the same as 'foo'.

$code = q{
    if( this is awesome ) {
        print "Look ma, no escaping!";
    }
};

To confuse your friends (and your syntax highlighter) try this:

$string = qq'You owe me $1,000 dollars!';
answered 2008-10-28T12:48:30.290
3

Very late to the party, but: attributes.

Attributes essentially let you define arbitrary code to be associated with the declaration of a variable or subroutine. The best way to use these is with Attribute::Handlers; this makes it easy to define attributes (in terms of, what else, attributes!).

I did a presentation on using them to declaratively assemble a pluggable class and its plugins at YAPC::2006, online here. This is a pretty unique feature.

answered 2008-11-21T20:27:52.090
3

You can use different quotes on HEREDOCS to get different behaviors.

my $interpolation = "We will interpolated variables";
print <<"END";
With double quotes, $interpolation, just like normal HEREDOCS.
END

print <<'END';
With single quotes, the variable $foo will *not* be interpolated.
(You have probably seen this in other languages.)
END

## this is the fun and "hidden" one
my $shell_output = <<`END`;
echo With backticks, these commands will be executed in shell.
echo The output is returned.
ls | wc -l
END

print "shell output: $shell_output\n";
answered 2010-05-26T14:10:53.300
2

The following are just as short but more meaningful than "~~" since they indicate what is returned, and there's no confusion with the smart match operator:

print "".localtime;   # Request a string

print 0+@array;       # Request a number
answered 2009-06-29T17:15:51.400
0

using bare blocks with redo or other control words to create custom looping constructs.

traverse a linked list of objects returning the first ->can('print') method:

sub get_printer {
    my $self = shift;
    {$self->can('print') or $self = $self->next and redo}
}
answered 2010-01-14T06:50:33.017
0

"now"

sub _now { 
        my ($now) = localtime() =~ /([:\d]{8})/;
        return $now;
}

print _now(), "\n"; #  15:10:33
answered 2010-09-06T17:25:31.913
0

B::Deparse - Perl compiler backend to produce perl code. Not something you'd use in your daily Perl coding, but could be useful in special circumstances.

If you come across some piece of code that is obfuscated, or a complex expression, pass it through Deparse. Useful to figure out a JAPH or a Perl code that is golfed.

$ perl -e '$"=$,;*{;qq{@{[(A..Z)[qq[0020191411140003]=~m[..]g]]}}}=*_=sub{print/::(.*)/};$\=$/;q<Just another Perl Hacker>->();'
Just another Perl Hacker

$ perl -MO=Deparse -e '$"=$,;*{;qq{@{[(A..Z)[qq[0020191411140003]=~m[..]g]]}}}=*_=sub{print/::(.*)/};$\=$/;q<Just another Perl Hacker>->();'
$" = $,;
*{"@{[('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z')['0020191411140003' =~ /../g]];}";} = *_ = sub {
    print /::(.*)/;
}
;
$\ = $/;
'Just another Perl Hacker'->();
-e syntax OK

A more useful example is to use deparse to find out the code behind a coderef, that you might have received from another module, or

use B::Deparse;
my $deparse = B::Deparse->new;
$code = $deparse->coderef2text($coderef);
print $code;
answered 2012-01-12T21:06:48.403

Your Answer