Hack 52. Make Invisible Characters Apparent


See what your variables really contain.

Perl has a handful of good debugging techniques. For example, you can fire up the debugger [Hack #59] or write test cases [Hack #53]. If you're just experimenting, or need a quick-and-dirty answer right now, sometimes the easiest technique is to add a few print( ) statements here and there.

This has its drawbacks, though, especially when the printed output looks correct but obviously isn't. Before you flip through the debugger documentation and rejig your debugging statements into test cases, consider a few tricks to make the invisible differences that your computer sees visible to you too. (Then make your test cases, use the debugger, and smarten your comments.)

Bracket Your Variables

A very common mistake is to forget to chomp( ) data read from external sources. Suppose that you're processing a list of files read from another file:

while (<$file_list>) {     warn "Processing $_";     next unless -e $_;     process_file( $_ ); }

All of the files look correct in the warn( ) output, but the process_file( ) code never occurs.

warn( ) is better than print( ) because it goes to STDERR by default, which makes it redirectable separately.


Change the debugging line to make the filename more visible:

while (<$file_list>) {     warn "Processing '$_'";     next unless -e $_;     process_file( $_ ); }

Adding single quotes (or any other visible character) around the filename will likely reveal that all of the filenames within the loop have newlines at the end (or whatever the current input record separator, $/, contains). The solution is obvious:

while (<$file_list>) {     chomp;     next unless -e $_;     process_file( $_ ); }

Bracket Interpolated Lists

The previous technique only works well on scalar variables. Lists and arrays are more tricky. Fortunately, the special punctuation variable $" controls the separator used when interpolating a list into a string.

Suppose that you're writing a ranking system for a table-tennis league. You've come to the end of the program and you want to display the top ten players:

my @ranked; for my $rank ( 1 .. 10 ) {     $ranked[$rank] = get_player_by_rank( $rank ); }

Of course, players may tieleaving two players at the third rank and no players at the fourth rank. The naïve approach of assuming the array contains exactly ten entries may fail, especially if get_player_by_rank( ) always only returns a single player or potentially returns an array reference of multiple players.

Printing the array may be no help:

for my $rank ( 1 .. 10 ) {     $ranked[$rank] = get_player_by_rank( $rank ); } warn "Ranks: [@ranked]\\n";

Everything interpolates into a single string, leaving you to count to see which is missing.

Instead, set $" to a nice, visible string:

local $" = '] ['; warn "Ranks: [@ranked]\\n";

This puts the delimiters between the entries, making it much easier to see which slot is empty.

If only you could override stringification on that particular array and print the index as well as the element at that index...roll on, Perl 6!


Serialize Your Data

If this is too much for you to handle manually, bring in the big guns of a serialization module to do your debugging for you. Data::Dumper has enjoyed a long reign as a nice debugging aid, but YAML provides even more readability and conciseness. To see a nested data structure (or even a scalar, array, or hash without having to worry about the right delimiters), use the Dump( ) function:

my $user = User->load( id => 54272 ); warn Dump( $user );

This prints a nice, compact representation of the data in the $user object without the excessive indentation and indirection that Data::Dumper can often provide.

Another good, if complex option, is using Devel::Peek to see exactly what Perl thinks of your variable. When you need it, you really need it. The rest of the time, take a breath, and then spend two minutes writing the test case.



Perl Hacks
Perl Hacks: Tips & Tools for Programming, Debugging, and Surviving
ISBN: 0596526741
EAN: 2147483647
Year: 2004
Pages: 141

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net