Rob Wells
Rob Wells

Reputation: 37103

Why is 'undef' not detected by this Perl fragment?

I would expect the block in the second 'if' statement to be entered because of the undef value but the logs show that it isn't being entered.

sub getcmd{
  my $self = $_[0];
  if ( $self->_recv == OK ){
      push @{$self->{'log'}}, ['NOTICE', "OK"];
      return "My command";          
  }
  push @{$self->{'log'}}, ['ERROR', "Did not get OK back"];
  return undef;
}

...

if (!($ret = $self->getcmd)){
  push @{$self->{'log'}}, ['ERROR', "failed to read after asking for NEXT"];
}
else {
  push @{$self->{'log'}}, ['ERROR', "'undef' not detected in next()"];
}

The log file shows:

[Fri May  8 19:25:56 2009]: ERROR: Did not get OK back
[Fri May  8 19:26:02 2009]: ERROR: 'undef' not detected in next()

Any ideas gratefully accepted.

Edit: Sorry, I'd edited down the code to show the basic flow. I should've proofread it a bit better.

Thanks for the suggestions and comments. I hadn't noticed the six second difference in the log timestamps so now I suspect that you're right about the execution sequence being different to what I originally expected.

I'll go back and look again. Guess that's what you get when trying to look at someone else's "average" Perl after a thirteen hour day trying to get things finished for a "must go live on Monday" project!

I didn't write the code and simply inherited it. The code was written by a couple of people who think they don't "need no steenking warnings or stricts".

Imagine 800 lines of Perl and lots of 'ifs' but no else statements! No defensive coding at all! 8-O

Upvotes: 2

Views: 556

Answers (4)

U. Windl
U. Windl

Reputation: 4325

The proper way to test $var for undef is not if (!$var) ..., because the test will also be true for $var = '' and $var = 0. Use if (!defined $var) ... instead.

Maybe like this (showing all relevant cases):

if (!defined $var) {
    # not defined ...
} elsif ($var) {
    # defined and true...
} else {
    # defined and false
}

Upvotes: 0

amarillion
amarillion

Reputation: 24917

Use perl debugger (perl -d) to step through the code to see what is going on. When debugging code, it's important to free your mind from every assumption.

Also, these lines are a must above every perl program:

use strict;
use warnings;

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753675

Reduced to a bare minimum, this prints "undef detected".

#!/bin/perl -w

use strict;

sub getcmd
{
    return undef;
}

my $ret;

if (!($ret = getcmd()))
{
    print "undef detected\n";
}
else
{
    print "undef undetected\n";
}

Consequently, your problem is most likely that the $self->getcmd() isn't returning undef, even though you think it should.

Upvotes: 7

Jonathan Rupp
Jonathan Rupp

Reputation: 15762

I think something more complicated is going on here -- those log messages seem to be 6 seconds apart, and there's no way it'd take 6 seconds for the push statement, the return, and the if check.

Any chance the first log message was from a previous call of the method from some other place in the application?

Upvotes: 2

Related Questions