Perl Lines of the Day from February, 1998

19 February, 1998

I didn't write much code today, because I had to go to the Federal Building to talk to the IRS folks. So I'm going to show this one item, even though it's not a single line as I'd prefer:

  while (<>) {
   die "No subject line found; aborting" 
     unless /\S/;		# Blank line: end of header
   next unless /^Subject:/;
   ($FILE) = /Responses to question (\w+)/;

This looks through the header of an email message for the Subject: line, and continues to the rest of the program once it has found it. I wrote it as part of a one-shot program that I planned to throw away soon afterwards, so I wasn't giving much thought to anything except making it work correctly.

I thought this loop was interesting because it only exits normally (through failure of the while condition) under the most abnormal of circumstances: end-of-file in the header of the message with no Subject: line.

Everything I've ever learned suggests that this loop, with its bizarre control flow, is very bad style, but I've looked it over and over, and it looks good to me, clear and straightforward. I can't decide if that's because it is, or if it's because there's something wrong with me. I'd be interested in your opinions on the matter.

18 February, 1998

	$revmemotable{$wrapper} = "$cref"; # Ha ha, Tom.

Tom Christiansen often castigates people for useless use of quotation marks in expressions like this: $r = &f(3, "$s"). He points out, quite rightly, that if $s here is a string or a number, the quotation marks are just useless and wasteful, and if $s is a reference, the quotation marks stringize it, which usually isn't what you want. This mistake can lead to program errors that are very difficult to track down; for example, consider the following line of code:

	$count = $p->count();

It yields ``Can't call method "count" without a package or object reference...'' But when you look with the debugger, $p appears to hold the right thing: Pie::Fruit=HASH(0x80f0340) or some such. The problem here is that somewhere along the way $p was stringized, and is no longer an array reference, but rather a string that prints out the same way.

However, in today's Line of the Day, this stringizing is exactly what is required. The package had a hash table, %memotable, which contained information about certain functions; this information was keyed by the stringized function reference. Given a reference to a function, you could stringize it and use the resulting string as a key to look up the information about the function, including a reference to a replacement for the function. %revmemotable was for reversing this lookup: If you know the replacement function, you can look in %revmemotable to find a hash key, which you can then use to look up the original function it replaced in %memotable. Since the values of %revmemotable are themselves hash keys, they should be strings. Storing the function reference $cref itself, rather than the stringized version, would have been erroneous, since it might have interfered with garbage collection.

At the suggestion of Roderick Schertler, I replaced the line above with one whose behavior is less subtle:

	$revmemotable{$wrapper} = "" . $cref; # Turn code ref into hash key

17 February, 1998

	my @c = ("\0" x (3*$X)) x $Y;

This line generates a pixel map canvas for an image rendering program. The structure canvas is an array of $Y lines of pixels $X pixels each. Each pixel is represented by three characters, representing an 8-bit value for the red, green, and blue intensities, respectively. The canvas is initialized to all black.

This line is notable for its use of the scalar and list modes of the x operator in the same place. Note that although it would have been funnier to use "\0" x 3 x $X instead of "\0" x (3*$X) here, the latter is probably a little more efficient because it doesn't have to create as many intermediate strings.

Return to: Universe of Discourse main page | What's new page | Perl Paraphernalia | Line of the Day