Sat, 13 Jan 2007

Inconceivable!

Every once in awhile, perl still gives me a surprise. This past week, I ran into a bug that had me stumped for quite awhile. I was using a common loop construct with an iterator object. But unexpectedly, the object returned by the iterator was getting trounced. I was getting “Can’t call method on an undefined value” errors.

In frustration, I added some diagnostics at the very top of the loop:

While ( my $obj = $iterator->next ) {
    warn "Inconceivable!" unless defined $obj;
    ...

Sure enough! The program began shouting warnings. How can $obj be defined in the loop conditional then undefined on the very next line of code? Inconceivable!

Or not. Perl provides another way to get to that next line of code.

Farther down in the code:

   # we need to skip some objects
   1 while ( $obj = $iterator->next && $obj->some_method );
   last unless $obj;
   redo;  # <-------- $obj is defined and healthy here

perldoc says:

The “redo” command restarts the loop block without evaluating the conditional again. The “continue” block, if any, is not executed. If the LABEL is omitted, the command refers to the innermost enclosing loop. Programs that want to lie to themselves about what was just input normally use this command…

Even though the conditional is not re-evaluated, $obj goes out of scope and we get and brand new, undefined $obj at the top of the loop, thanks to the my declaration in the loop conditional. That makes some sense (perfect sense if you understand the perl internals—I can’t claim that). It caught me off guard.

One simple way to solve the problem is to move the my declaration outside the loop. In my case, I was able to eliminate need for the redo.

Another lesson learned—the only way they stick—the hard way.

[/programming] [link]

About this weblog

This site is the personal weblog of Marc Mims. You can contact Marc by sending e-mail to:
[email protected].

Marc writes here about cycling, programming, Linux, and other items of personal interest.

This site is syndicated with RSS.

Archives

Credits

CSS stolen from Tom Coates who didn't even complain.