Reputation: 191
I am not a heavy perl user. I am just learning. However, recently I am working with an old script written by someone else. Essentially, the script reads an input file from which the variable "index_a" is defined such that when doing a simple print:
print "$index_a";
00
My confusion comes from the following:
When a comparison to "zero" is made, it holds true:
if ($index_a == 0) { print "Found first index: 0" };
Found first index: 0
I was expecting the comparison to be false. Since the value of index_a = 00 is obtained from reading a line from an input file. Hence to my understanding index_a is a string which value is "00", therefore the if statement should not be executed.
Could some perl expert help me understand this? Also, could you let me know what is the proper way to check for data types in perl? I have experience with python and C and hence this is behavior is very confusing to me.
Thanks!
Upvotes: 3
Views: 604
Reputation: 132783
When you use a Perl string in a numeric context, such as a numeric comparison, it recognizes the starting part that looks like a decimal number and ignores the stuff after that. Whatever it recognizes becomes the number.
It follows these basic rules:
+
or -
)There are some things to note, though:
123_456
is 123456
because the perl parser handles the _
, but '123_456'
is just 123
.-
sign but not the +
sign. This is the special IEEE value of Infinity.Here are some examples:
#!perl
use v5.10;
use utf8;
use open qw(:std :utf8);
my @strings = qw(
-5 +7 +006 -01 00
+.1234 -.9876 .657 ..890 1.2.3
١٢٣
- + +-657
12a34 a987 123fred 0456barney
0x12 12_34 0177
NaN -NaN NAN
Inf +Inf -Inf INF Infamy Infinity
);
push @strings, " 432", "+ 123", " -987", " +063"," NaN", " Inf", '';
foreach my $string ( @strings ) {
printf "%-12s => %s\n", qq('$string'), 0 + $string;
}
And the output:
'-5' => -5
'+7' => 7
'+006' => 6
'-01' => -1
'00' => 0
'+.1234' => 0.1234
'-.9876' => -0.9876
'.657' => 0.657
'..890' => 0
'1.2.3' => 1.2
'١٢٣' => 0
'-' => 0
'+' => 0
'+-657' => 0
'12a34' => 12
'a987' => 0
'123fred' => 123
'0456barney' => 456
'0x12' => 0
'12_34' => 12
'0177' => 177
'NaN' => NaN
'-NaN' => NaN
'NAN' => NaN
'Inf' => Inf
'+Inf' => Inf
'-Inf' => -Inf
'INF' => Inf
'Infamy' => Inf
'Infinity' => Inf
' 432' => 432
'+ 123' => 0
' -987' => -987
' +063' => 63
' NaN' => NaN
' Inf' => Inf
'' => 0
Finally, there's another interesting thing about Perl scalars. When you use a string as a number, Perl converts the string to a number and remembers the conversion. It does not, however, change the string. Devel::Peek
shows you the innards of Perl data structures.
#!perl
use v5.10;
use Devel::Peek;
select(STDERR); $|++; # just to order the output from Dump
my $string = '123fred';
say "string is <$string>";
Dump( $string );
say '-' x 40;
my $n = $string + 0;
say "string is <$string>";
Dump( $string );
Here's the output. At first, $string
has a PV
(pointer value) for a string. After the numeric operation, it also has IV
and NV
values for numbers.
string is <123fred>
SV = PV(0x7f8be980cab0) at 0x7f8bea0160f8
REFCNT = 1
FLAGS = (POK,IsCOW,pPOK)
PV = 0x7f8be9610ca0 "123fred"\0
CUR = 7
LEN = 10
COW_REFCNT = 1
----------------------------------------
string is <123fred>
SV = PVNV(0x7f8be980ac50) at 0x7f8bea0160f8
REFCNT = 1
FLAGS = (POK,IsCOW,pIOK,pNOK,pPOK)
IV = 123
NV = 123
PV = 0x7f8be9610ca0 "123fred"\0
CUR = 7
LEN = 10
COW_REFCNT = 1
Upvotes: 2
Reputation: 67900
In Perl, the context is important when considering the value. A scalar variable can contain all sorts of data types, but what you are testing for determines what you find. For example:
if ("00" == 0) # string "00" is numerically identical to 0
if ("a" == 0) # string "a" is numerically identical to 0 (gives a warning)
# Argument "a" isn't numeric in numeric eq (==)
if ("00" eq "0") # string "00" is not stringwise identical to "0".
if (@a == 0) # if the array @a is empty (length 0)
In a numerical equality check with a string, Perl will try to cast the string to a number. If the string begins with a number, it will be cast to that number (for the duration of the test), else it will be cast to 0
.
You have to (sort of) know what you have in a variable when you test what it contains. Or else you have to check more thoroughly. In your case, when reading from a file, you might want to use eq
to test for string equality.
Upvotes: 7