Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:


I have decided to try to figure out Acme::Bleach. It's only 13 lines of code. But that's 13 lines of Conway's code. I have also looked at similiar modules, such as Acme::Buffy, Acme::Buckaroo, and others, but I want to stick with Acme::Bleach. There's just something about Conway's coding style. Anyway, this is what I know about what the module does: Acme::Bleach encodes/decodes the source of the program. But *how* it does this leaves me a little confused. Let's go through this line by line:

1: package Acme::Bleach; 2: $VERSION = '1.12'; 3: my $tie = " \t"x8; 4:sub whiten { local $_ = unpack "b*", pop; tr/01/ \t/; s/(.{9})/$1\n/ +g; $tie.$_ } 5: sub brighten { local $_ = pop; s/^$tie|[^ \t]//g; tr/ \t/01/; pack +"b*", $_ } 6: sub dirty { $_[0] =~ /\S/ } 7: sub dress { $_[0] =~ /^$tie/ } 8: open 0 or print "Can't rebleach '$0'\n" and exit; 9: (my $shirt = join "", <0>) =~ s/.*^\s*use\s+Acme::Bleach\s*;\n//sm; 10: local $SIG{__WARN__} = \&dirty; 11: do {eval brighten $shirt; exit} unless dirty $shirt && not dress $ +shirt; 12: open 0, ">$0" or print "Cannot bleach '$0'\n" and exit; 13: print {0} "use Acme::Bleach;\n", whiten $shirt and exit;

Basically, Conway has 4 subroutines (whiten, brighten, dirty, dress) in lines 4 - 7. These subroutines appear to do the encoding/decoding, right? Why does he use "local" so much? Anyway, the names are interesting: I assume that whiten would bleach the code, that is, turn the code into white space and tabs, etc. . . But what about brighten? It sounds like they would do the same thing. However, whiten sounds like it would do the bleaching (encoding) and brighten would do the decoding, right? I base these assumptions on the next lines.

In lines 8 and 9, the current script is opened and everything up to and including "use Acme::Bleach" line is omitted from the $shirt variable. That's easy to figure out. Now I note that in line 8 the script is opened for *reading*. I conclude that the source code at this point is not being encoded since nothing yet is being written to the file. I don't understand line 10. He seems to be catching a warning signal for some reason. Why?

Line 11 seems crucial: the content of $shirt is evaluated (i.e, executed) if the source code is not dirty (bleached or whitened). But why does he also test if the $shirt is dressed? I don't see the purpose of the dress subroutine. The dirty subroutine is used to test if the source code has been bleached or not. So why does he need to have another subroutine for? If the dirty subroutine tests if the whitening (encoding) has occurred, then maybe the dress subroutine tests if the code has been brightened (decoded)? I am not sure . . .

I guess most of my confusion stems from my lack of knowledge concerning the pack, unpack, local, pop, translate functions. For example, I have never seen someone use tr/01/ \t/ before as Conway does in the whiten subroutine.

At first, the final lines seem pretty transparent. But I find these also bewildering. I believe that in lines 12 and 13, the source code is encoded (bleached), BUT why does he print "use Acme::Bleach" before he whitens? Yes, I recall that "use Acme::Bleach" is omitted from the $shirt variable, but how come having this use statement is necessary for your code to execute twice? I noticed that if I omitt or otherwise modify this line, then the code doesn't work.

The flow of this program escapes me. I have a strong feeling that a flow chart of this program would be very enlightening. The first time the module is called, the source code is bleached, but the next time the code is called the source code is brightened (decoded). But HOW can your program know to use Conway's module after your program has been bleached? Shouldn't line 13 print the perl hash line before the use statement?