Приглашаем посетить
Дмитриев (dmitriev.lit-info.ru)

Section 10.2.  Just Another Perl Hacker

Previous
Table of Contents
Next

10.2. Just Another Perl Hacker

A long time ago, in a Usenet newsgroup far, far away, Perl hacker Randal Schwartz (coauthor of Learning Perl and the early Programming Perl books) signed off a Usenet post with the famous words:

    Just another Perl hacker,

Of course, since Randal was talking about Perl and demonstrating techniques in Perl, this signature very soon mutated into the very obvious Perl code:

    print "Just another Perl hacker,\n";

and at this point, the JAPH was born. As Randal and others demonstrated a Perl programming technique in their Usenet articles, the point would be highlighted by a valedictory JAPH. For instance, when demonstrating the fact that sort sorts lexicographically with uppercase characters first, one might sign off:

    print join" ", (sort(qw(another Just Perl hacker,)))[0,2,1,3];

Since then, it has become a Perl tradition to produce programs that output the words "Just another Perl hacker" in cute, educational, or unexpected ways. The undisputed kingor perhaps, queenof JAPHdom is the Dutch hacker Abigail, who has contributed some of the most surprising JAPHs to the Perl community. The JAPH culture is so established that some of Abigail's JAPHs have been included in recent versions of Perl as regression tests, since they expose some of the strangest edge cases of the perl interpreter's behavior.

Abigail's JAPHs use many of the tricks involved in obfuscated Perl but always end up surprising many readers. For instance, here's one of the more famous ones:

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
    % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %;
    BEGIN {% % = ($ _ = " " => print "Just another Perl Hacker\n")}

The fact that this prints out a JAPH should be no surprise, since this is given entirely in the last line; the surprise should be in the fact that the whole thing parses as valid Perl code. But if you remember that // is a valid pattern match, %% is a perfectly good name for a hash, and ** is a perfectly good glob, then all should become relatively clear.

There's a varying degree of complexity involved in JAPHs. The most basic JAPH somehow encodes the JAPH string, and then decodes it. This is pretty boring:

    $_ = q ;4a75737420616e6f74686572205065726c204861636b65720as;;
         for (s;s;s;s;s;s;s;s;s;s;s;s)
             {s;(..)s?;qq qprint chr 0x$1 and \161 ssq;excess;}

Then there are the kind of JAPHs that obviously contain the JAPH string, but it's not at all obvious how it reaches standard output:

    eval {die [[qq [Just another Perl Hacker]]]};; print
    ${${${@}}[$#{@{${@}}}]}[$#{${@{${@}}}[$#{@{${@}}}]}]

And then there are those JAPHs that look like they might contain something like the JAPH string, but the rest is unclear:

    BEGIN {$^H {q} = sub {$_ [1] =~ y/S-ZA-IK-O/q-tc-fe-m/d; $_ [1]}; $^H= 0x28100}
    print "Just another PYTHON hacker\n";

This particular JAPH relies upon a little-known feature of the overload pragmaexplained in Chapter 1combined with a little-known feature of its implementationthe fact that it relies on placing specific values in the magic variables $^H and %^H.

A similar effect, it turns out, can be obtained by tying special variables:

    tie $" => A; $, = " "; $\ = "\n"; @a = ("") x 2; print map {"@a"} 1 .. 4;
    sub A::TIESCALAR {bless \my $A => A} #  Yet Another silly JAPH by Abigail
    sub A::FETCH     {@q = qw /Just Another Perl Hacker/ unless @q; shift @q}

Here, the $" variable, which is used to join array elements when they are interpolated in double-quoted strings, is tied; hence, when we interpolate the (empty) array @a, the tied variable pulls out another word from the JAPH string stored in @q.

Special variables also play an interesting part in this Abigail creation, but in a very different way:

    map{${+chr}=chr}map{$_=>$_^ord$"}$=+$]..3*$=/2;
    print "$J$u$s$t $a$n$o$t$h$e$r $P$e$r$l $H$a$c$k$e$r\n";

This takes advantage of the very fortuitous coincidences that the value of $= (the default number of lines on a format page) plus $] (the Perl version, generally just over 5 for now) is 65, the ASCII code for "A," and three-over-two times $= is 90, the ASCII code for "Z." Combined with the fact that the ASCII character set is arranged so that you can flip between lower- and uppercase letters by flipping the 5th bit (32, the value of a space character, as stored in $"), the first line of this JAPH sets $a to a, $b to b, and so on through to $Z; once this is accomplished, the second line follows naturally.

$A++

This discipline was invented by the Paris Perl Mongers, who also host a list of results at http://paris.mongueurs.net/aplusplus.html. The challenge is to increment the value of $A by one. There are currently 288 entries, ranging from the simple:

    $A++;

to the mind-blowing:

    y ccccd x s vvchr oct oct ord uc ave x s vvucve le
    s vvuc ave x s vvchr oct oct oct ord uc bve x eval


    Previous
    Table of Contents
    Next