Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Peculiar incident: printing a variable changes its type

by mkhan (Sexton)
on Nov 13, 2013 at 09:08 UTC ( #1062356=perlquestion: print w/ replies, xml ) Need Help??
mkhan has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I just scratched my head for a good chunk of my time resolving an issue which boils down to this:
use JSON; $params->{timeout} = 2000; $body->{"timeout"} = (defined $params->{timeout}?$params->{timeout} : +3000); print "$body->{timeout}\n"; #<-----suspect line my $body_string = to_json($body); print "$body_string";
In the above code, the mere printing of the hash value adds double quotes to the timeout value in the json as shown in the output.
Output: 2000 {"timeout":"2000"}
Now if you remove the "suspect line" from the above code:
use JSON; $params->{timeout} = 2000; $body->{"timeout"} = (defined $params->{timeout}?$params->{timeout} : +3000); my $body_string = to_json($body); print "$body_string";
Output: {"timeout":2000}
In the second output, the value 2000 wasn't wrapped in quotes. I find it really peculiar as to why the mere printing of the hash value changes the behavior of the output??

Comment on Peculiar incident: printing a variable changes its type
Select or Download Code
Re: Peculiar incident: printing a variable changes its type
by mje (Curate) on Nov 13, 2013 at 09:23 UTC

    Use Devel::Peek and Dump $body->{"timeout"} before and after print. Look at the part called pv. I'm afraid this is what a lot of JSON encoders do, they try to guess whether something is a number by looking to see if your scalar has a pv (has been used in string context) or not. printing your scalar causes the pv to be created.

    Some modules (e.g., DBD::Oracle and DBD::ODBC) have had code added to them to allow an attribute to be specified to remove the pv when fetching numbers from a database but this is XS code. I'm unsure how you do it in pure perl but there is bound to be a way.

Re: Peculiar incident: printing a variable changes its type
by tobyink (Abbot) on Nov 13, 2013 at 09:28 UTC

    Strings and numbers in Perl are represented by the same data type: scalars. When the JSON module encounters something that looks like a number, it has to guess whether you wanted to output it as a number or a string. To do this it peeks at the scalar's internals (the SV structure - in particular, its flags) to see whether the scalar has ever been treated as a string. If it has, then it outputs it as a quoted string.

    Install Devel::Peek and note the difference here:

    $ perl -MDevel::Peek -E'my $x = 1; print "$x\n"; print Dump($x)' 1 SV = PVIV(0x864e218) at 0x864d738 REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 1 PV = 0x86483a8 "1"\0 CUR = 1 LEN = 12 $ perl -MDevel::Peek -E'my $x = 1; print $x,"\n"; print Dump($x)' 1 SV = IV(0x86b0724) at 0x86b0728 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 1

    In the first example, the variable $x has been interpolated into a string, and thus acquires a POK flag indicating that the SV structure has a pointer to a string. In the second example, although $x has still been printed out, with a new line afterwards, there was no concatenation; no string operator performed on $x; so it doesn't acquire a POK flag. The JSON module would output this as a number.

    You can make a variable's POK flag disappear by adding 0 to it:

    $ perl -MDevel::Peek -E'my $x = 1; print "$x\n"; $x += 0 ;print Dump($ +x)' 1 SV = PVIV(0x9cba210) at 0x9cb9730 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 1 PV = 0x9cb43a0 "1"\0 CUR = 1 LEN = 12

    Notice that the actual string pointer has been kept (that's the PV line), but it is no longer "OK" - it might have been invalidated by the addition, so the POK flag has gone.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
      Install Devel::Peek
      According to corelist, Devel::Peek is a core module since 5.6.0.
      لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Peculiar incident: printing a variable changes its type
by KurtZ (Beadle) on Nov 13, 2013 at 14:07 UTC
    print "$body->{timeout}\n"; #<-----suspect line
    avoid stringification!
    print $body->{timeout}, "\n"; # better
    HTH!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1062356]
Approved by mje
Front-paged by mje
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2015-07-03 03:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (48 votes), past polls