Using the perl eq operator changes the type of arguments

I made this script to check how scalars change when using "eq" instead of "==" randomly and vice versa. Using '==' in strings does not change anything, but using 'eq' on numbers makes a scalar change in some way. Here is 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" } 

Using words, the number $ num changes from number to line. Commenting out a line

 if ($num eq "123") { } 

$ num no longer changes. Is this a bug or function? Why is this happening? 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 
+7
perl perl-data-structures
source share
1 answer

Perl variables are multi-valued, for example. 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 number or whole slots will be updated and marked as real. In your example, $ str will initially have a valid line slot, and after comparing with an integer, it will also have a valid integer slot. If you compared it to a float, it would have a valid float slot instead. You can check this with Devel :: Peek :: Dump: POK means a valid line slot, IOK is a valid integer slot and NOK is a valid floating point slot.

Similar things happen if you store an integer and later use it as a string. In your example, $ num will first have a valid integer slot (IOK), and as soon as you access it as a string (using eq), it will be converted to a string, and the string slot will be filled and valid (POK) additionally in integer slot.

to_json probably just looks at the variable and takes the first valid slot that it finds, starting from the line (I assume it should be encode_sv in JSON :: XS - this is checked in the following order: string, float, integer). Therefore, if the string slot is valid, it will be printed with quotation marks around it.

Other languages ​​(e.g. python) do not have this multi-slot thing, they just have one type, and if you use the variable in a different context, it will scream. Both ways have their pros and cons :)

+6
source share

All Articles