I made this script to check how scalars change when accidently using 'eq' instead of '==' and vice versa. Using '==' on strings changes nothing but using 'eq' on numbers makes the scalar change somehow. Here comes the code:
#!/usr/bin/perl
use strict;
use JSON;
my $str = "123";
my $num = 123;
print "BEFORE:\n";
print "str: ", \$str, " num: ", \$num, "\n";
print to_json({str => $str, num => $num}, {pretty => 1});
if ($str == 23) { }
if ($num eq "123") { }
print "AFTER:\n";
print "str: ", \$str, " num: ", \$num, "\n";
print to_json({str => $str, num => $num}, {pretty => 1});
print "\n";
Output:
BEFORE:
str: SCALAR(0x8010f8) num: SCALAR(0x801050)
{
"num" : 123,
"str" : "123"
}
AFTER:
str: SCALAR(0x8010f8) num: SCALAR(0x801050)
{
"num" : "123",
"str" : "123"
}
With words, $num is changed from being a number to being a string. By commenting the line
if ($num eq "123") { }
$num is not changed anymore. Is this a bug or feature? Why does this happen? Also, how can I see this without using to_json?
perl --version
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
== is used when comparing numeric values. eq is used in comparing string values. = is the assignment operator, not a comparison operator.
'eq' operator in Perl is one of the string comparison operators used to check for the equality of the two strings. It is used to check if the string to its left is stringwise equal to the string to its right.
Perl variables are multivalued, e.g. they have slots for string, integer, floating point and reference.
If you assign a string to a variable it will be stored in the string slot and this slot will be marked as valid. If you later access the variable as a number, the string will be converted and the floating point or the integer slots will be updated and marked valid. In your example $str will initially have a valid string slot and after the comparison with an integer it will also have valid integer slot. If you would have compared it with a float it would have a valid float slot instead. You might check this with Devel::Peek::Dump: POK means valid string slot, IOK is a valid integer slot and NOK a valid float slot.
Similar things happen, if you store an integer and later use it as a string. In your example $num will have initially a valid integer slot (IOK) and once you access it as a string (by using eq) it will be converted to a string and the string slot will be filled and be valid (POK) additionally to the integer slot.
to_json probably just looks at the variable and takes the first valid slot it finds, starting with the string (I guess this must be encode_sv in JSON::XS - this checks in this order: string, float, integer). So if the string slot is valid it will be printed with quotes around it.
Other languages (like python) don't have this multi-slot thing, they just have a single type and if you use the variable in another context it will croak. Both ways have their pros and cons :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With