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 :)
Steffen ullrich
source share