chidori
chidori

Reputation: 1112

What does Perl return when a numeric comparison is false?

I am trying to execute this code. What puzzles me is why doesn't this comparison return any value when false. Is this the default behavior of these comparison operators?

my $output = (2 <= 1); 
print "value=$output";

Will a comparison operator return undef when its logical check fails?

Upvotes: 4

Views: 1374

Answers (4)

brian d foy
brian d foy

Reputation: 132802

The relational operators

return 1 for true and a special version of the defined empty string, "" , which counts as a zero but is exempt from warnings about improper numeric conversions, just as "0 but true" is.

The value you get back is actually a dualvar. It has separate numeric and string values (not a special version of the empty string, really). The numeric value is 0 and the string value is the empty string. You used the string portion, which is empty, but the 0 is still there. You can look inside the variable records with Devel::Peek:

use Devel::Peek;
my $result = ( 1 == 2 );
Dump( $result );

In the SV (scalar value) thing behind the scenes, you see the string value in the PV and the numeric value in the IV And NV (the integer and numeric values):

SV = PVNV(0x7fe602802750) at 0x7fe603002e70
  REFCNT = 1
  FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 0
  NV = 0
  PV = 0x7fe6026016b0 ""\0
  CUR = 0
  LEN = 16

There are other sorts of dualvars too. The $! error variable has the error number and the error text, for instance (and I talk about that in Mastering Perl). This isn't something you normally have to worry about because Perl does the right thing for the context.

If you always want a numeric value, use it in a numeric context:

my $numeric = 0 + $result;   # 0

You can create your own dualvars with Scalar::Util's dualvar, and you can check if a scalar is a dualvar with isdual.

use Scalar::Util qw(isdual);
my $result = ( 1 == 2 );
print isdual($result) ? "dualvar" : "Not dualvar";

If you wanted to check that the value you got back was defined (you said it wasn't), you can check with defined. An empty string is defined, though. If you want to check that it's not the empty string, you can use length. These help when the value you have isn't printable.

Upvotes: 13

brainbuz
brainbuz

Reputation: 444

Comparisons can return a special false value that is an empty string or 0 depending on the context in which it is evaluated. If you are looking for specific values for true and false it is much safer to use a statement like this:

my $output = ( 2 <= 1 ) ? 1 : 0;

The following code will illustrate the behaviour of the special false value.

use 5.014; 
say ( 2 <= 1); # prints nothing
my $output = ( 2 <= 1 ) ? 1 : 0; 
say $output; # prints 0
$output = ( 2 > 1 ) ? 1 : 0 ; 
say int $output; # prints 1
say $output; # prints 1
$output = ( 2 <= 1 ) ; 
say int $output ; # prints 0

If you're unfamiliar with the ? : construct see: http://perldoc.perl.org/perlop.html#Conditional-Operator

Upvotes: 1

Miguel Prz
Miguel Prz

Reputation: 13792

That expression returns an empty string (""), which Perl considers as a false value in evaluating sentences like if or unless.

In Perl, 0, "0" and an empty string ("") are false. undef is also false, but you may get a warning. Anything else is true.

Upvotes: -1

JGNI
JGNI

Reputation: 4013

Boolean operators return 1 on true and '' on false. You are trying to print the empty string.

Try this for a test

use strict;
use warnings;
my $output = (2 <= 1); 
print $output ? "value=|$output|" : "value=<$output>";

Upvotes: 3

Related Questions