10.5. Acme::*
With all this crazy hackery going on, an outlet was needed on CPAN for less serious module contributions to the Perl world. The
Acme
namespace was set aside for wacky, explosive, or Heath-Robinsonian modules, and has very quickly become one of the more densely
It all started with the Bleach module, a neat toy by Damian Conway that spawned a host of less amusing and sadly uninspired imitators. Because of the host of imitators that followed, clogging up the root of the CPAN namespace, it was decided that silliness should not be discouraged, but moved to Acme:: , and Bleach became Acme::Bleach . Bleach is really clever; it takes an ordinary program, like so:
use Bleach;
for my $i (1..10) {
print "Hello! $i\n";
}
The first time this program runs, it appears to do nothing at all. However, when you come to look at the code again, it now looks like: use Bleach; The really clever part is that it still runs, and it now prints out the message 10 times. This is astonishing until you know the trick. How does Bleach work, then? Everyone assumed this was done with source filters, but the business end of Bleach is a mere 11 lines long:
my $tie = " \t"x8;
sub whiten { local $_ = unpack "b*", pop; tr/01/\t/; s/(.{9})/\n/g; $tie.$_ }
sub brighten { local $_ = pop; s/^$tie[^ \t]//g; tr/ \t/01/; pack "b*", $_ }
sub dirty { $_[0] =~ /\S/ }
sub dress { $_[0] =~ /^$tie/ }
open 0 or print "Can't rebleach'
It all becomes pretty obvious when you look at what the subroutines do. The
whiten
subroutine takes a string, turns it into its binary representation, and turns the zeros and ones into different types of whitespace. The
brighten
subroutine does the
So the module loads up your code by using a slightly nifty Perl trick, found in the documentation of open :
That is, by opening a filehandle called
, we take the filename from
$0
, the location of our program. Then we lop off everything before
use Acme::Bleach
, and
Very simple, once you've seen the trick. Other modules based on the same principle include Acme::Buffy , Acme::Pony , and many other London.pm in-jokes. There are, of course, some Acme:: modules that do other things. They range from the amusing but simple and uninspired ( Acme::Handwave you tell it what data you expect, and it returns it), through amusing, simple, and inspired ( Acme::Don't like a do block, but not quite) right up to the spectacular.
Acme::Eyedrops
, for instance,
print "hello world\n"; and automatically obfuscates it:
perl -MAcme::EyeDrops=sightly -e 'print sightly("helloworld.pl")'
eval eval
'"'.('['^'+').('['^')').('`'')').('`''.').('['^'/').('{'^'[').'\'.'"'.
('`''(').('`''%').('`'',').('`'',').('`''/').('{'^'[').('['^',').('`'
'/').('['^')').('`'',').('`''$').'\'.'\'.('`''.').'\'.'"'.';'.('!'^
'+').'"'
(We've reformatted the actual output slightly for, um, readability.)
Now you can probably see what it's done hereit's encoded the ASCII values of each character in the program: the first character is
'[' ^ '+'
, which is
p
, and so on. But that's not all it can do; it can pour that mess of punctuation into pretty
eval eval '"'.
('['^'+').("\["^
')').("\`" ')').('`'
'.').('['^'/' ).('{'^'[')
.'\'.'"'.("\`" '(').(('`')
'%').('`'(',')).( '`'',').('`'
'/').('{'^'[').('['^ ',').('`''/'
).('['^')').('`'',').( '`''$').'\'
.'\'.('`''.').'\'.'"' .';'.('!'^'+')
.'"';$:='.'^'~';$~='@''(' ;$^=')'^'[';$/
='`''.';$_='('^'}';$,='`' '!';$\=')'^'}';
$:='.'^'~';$~=('@') '(' ;$^ =')'^'['
;$/='`''.';$_='(' ^'}';$,
='`''!';$\=(')')^ '}';$:=
'.'^'~';$~='@''(' ;($^)=
')'^'[';$/='`''.'; $_='('
^'}';$,='`''!';$\= "\)"^
'}';$:='.'^"\~";$~= ( '@')
'(';$^=')'^'[';$/ = '`'
'.';$_='('^'}';$, = ((
'`'))'!';$\="\)"^ ( ((
'}')));$:='.'^'~'; ( ( ( ( ( ( (
$~)))))))='@'"\("; ( ( ( ( (
$^)))))=')'^'[';$/ ='`' '.' ; (
( $_))='('^'}';$, ='`''!' ;($\) = (
( ')'))^'}';$: = (
'.')^"\~"; ( $~)
= '@' (
( ( (
( ( (
( ( (
( ( ( ( ( ( (
( ( ( ( (
( ( ( (
( (
( (
( ( '(')))))) )
) ) )))))))))))))
) ) )))))))) ;
( ( $^))=')'^'[';
# ; # ;
# ; # ;
# ; #
; # ; # ;
# ;
# ;
# ;
# ; #
; #
Some modules are perhaps better left unwritten.
On the other hand, there are some
Acme::
modules that are interesting ideas in other ways
Acme::Your
, for instance, works like
our
, but you get to use unqualified package
A final
Acme
Hello World Souffle.
This recipe prints the immortal words "Hello world!", in a basically
brute force way. It also makes a lot of food for one person.
Ingredients.
72 g haricot beans
101 eggs
108 g lard
111 cups oil
32 zucchinis
119 ml water
114 g red salmon
100 g dijon mustard
33 potatoes
Method.
Put potatoes into the mixing bowl. Put dijon mustard into the mixing
bowl. Put lard into the mixing bowl. Put red salmon into the mixing
bowl. Put oil into the mixing bowl. Put water into the mixing
bowl. Put zucchinis into the mixing bowl. Put oil into the mixing
bowl. Put lard into the mixing bowl. Put lard into the mixing
bowl. Put eggs into the mixing bowl. Put haricot beans into the mixing
bowl. Liquify contents of the mixing bowl. Pour contents of the mixing
bowl into the baking dish.
Serves 1.
Acme::Chef
comes with a Chef interpreter and a compiler to turn Chef programs into Perl programs. I can't help wondering how much programmer time gets spent on this
|