Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use of perl's eq operator changes type of the arguments

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
like image 753
Manne Tallmarken Avatar asked Jan 08 '14 10:01

Manne Tallmarken


People also ask

What is the difference between == and EQ in Perl?

== is used when comparing numeric values. eq is used in comparing string values. = is the assignment operator, not a comparison operator.

What is EQ in Perl?

'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.


1 Answers

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 :)

like image 94
Steffen Ullrich Avatar answered Oct 20 '22 04:10

Steffen Ullrich