Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining if a perl scalar is a string or integer

From what I read, perl doesn't have a real type for integer or string, for him any $variable is scalar.

Recently I had a lot of trouble with an old script that was generating JSON objects required by another process for which values inside JSON must be integers, after some debug I found that because a simple print function:

JSON::encode_json

was generating a string instead an integer, here's my example:

use strict; 
use warnings; 
use JSON;
my $score1 = 998;
my $score2 = 999;
print "score1: ".$score1."\n";
my %hash_object = ( score1 => $score1, score2 => $score2 );
my $json_str = encode_json(\%hash_object);  # This will work now
print "$json_str";

And it outputs:

score1: 998
{"score1":"998","score2":999}

Somehow perl variables have a type or at least this is how JSON::encode_json thinks.

Is there a way to find this type programmatically and why this type is changed when making an operation like the concatenation above?

like image 616
Adrian Toma Avatar asked Feb 05 '16 15:02

Adrian Toma


1 Answers

First, it is somewhat incorrect. Yes, every values is scalar, but scalars have separate numeric and string values. That's all you need to know for this particular question, so I'll leave details out.

What you really need is to take a look at MAPPING / PERL -> JSON / simple scalars section of documentation for JSON module:

JSON::XS and JSON::PP will encode undefined scalars as JSON null values, scalars that have last been used in a string context before encoding as JSON strings, and anything else as number value.

(The docs are actually slightly wrong here. It is not "last been used in string context" it should be "was ever used in string context" - once scalar obtains string value it won't go away until you explicitly write a new number into it.)

You can force the type to be a string by stringifying it:

my $x = 3.1; # some variable containing a number
"$x";        # stringified
$x .= "";    # another, more awkward way to stringify
print $x;    # perl does it for you, too, quite often

Incidentally this comment above is exactly about why your 998 turned to string.

You can force the type to be a number by numifying it:

my $x = "3"; # some variable containing a string
$x += 0;     # numify it, ensuring it will be dumped as a number
$x *= 1;     # same thing, the choice is yours.
like image 59
Oleg V. Volkov Avatar answered Sep 28 '22 08:09

Oleg V. Volkov