Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

A somewhat unexpected side effect...

by blazar (Canon)
on Nov 21, 2006 at 11:40 UTC ( [id://585235]=perlmeditation: print w/replies, xml ) Need Help??

Although a documented one... basically I just want to report an interesting entry in the Journal of DAxelrod (who is also a fellow monk here), at use Perl.

To cut it short, the following:

#!/usr/bin/perl use strict; use warnings; my ($num, $let, $foo); $num = "z"; $let = $num; # $foo = 1 + $num; # this does not modify $num $num++; $let++; print "num:$num let:$let\n"; __END__

outputs

num:aa let:aa

whereas if you uncomment line 9, it will issue a

Argument "z" isn't numeric in addition (+) at C:\temp\foo.pl line 9.

warning, and output

num:1 let:aa

which is as of the subject, surprising and unexpected due to the fact that $num is just used, but appearently not modified in any way whatsoever. However, as the original article itself says this is both documented and useful for obfu. In this respect I was thinking that a particularly confusing effect could be achieved if one used e.g. "9" instead of "z", but that doesn't seem to be the case:

C:\temp>perl -le "$a='z';print++$a" aa C:\temp>perl -le "$a='9';print++$a" 10

B::Concise seems to say the same for both:

C:\temp>perl -MO=Concise -e "$a='z'" >z -e syntax OK C:\temp>cat z 6 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 5 <2> sassign vKS/2 ->6 3 <$> const[PV "z"] s ->4 - <1> ex-rv2sv sKRM*/1 ->5 4 <#> gvsv[*a] s ->5 C:\temp>perl -MO=Concise -e "$a='9'" >9 -e syntax OK C:\temp>diff z 9 5c5 < 3 <$> const[PV "z"] s ->4 --- > 3 <$> const[PV "9"] s ->4

(Note: damn! I couldn't use | diff z - under Windows.)

Fortunately, this is perfectly well documented as well:

The auto-increment operator has a little extra builtin magic to it. If you increment a variable that is numeric, or that has ever been used in a numeric context, you get a normal increment.

This obviously mean that "that is numeric" comprises "that looks like a number". How much it may resemble one, though, is not very intuitive. I do know it's more or less Perl's standard behaviour, but I for one would expect the string to be treated as a string in both of the following:

C:\temp>perl -le "$a='foo9';print++$a" fop0 C:\temp>perl -le "$a='9bar';print++$a" 10

Replies are listed 'Best First'.
Re: A somewhat unexpected side effect...
by Anonymous Monk on Nov 21, 2006 at 12:14 UTC
    You put the emphasis on the wrong part of the quoted documentation. The essential part is has ever been used in a numeric context. Either side of binary + is classifies as numeric context.

    The more technical reason is "you get normal increment if the SV isn't a PV".

    perl -MDevel::Peek -e '$n = "z"; Dump($n); $f = 3 + $n; Dump($n)' SV = PV(0x804def8) at 0x8063ad0 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x805cce8 "z"\0 CUR = 1 LEN = 2 SV = PVNV(0x8080dc0) at 0x8063ad0 REFCNT = 1 FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x805cce8 "z"\0 CUR = 1 LEN = 2
    As you can see, the variable does change by just looking at it.
      You put the emphasis on the wrong part of the quoted documentation. The essential part is has ever been used in a numeric context. Either side of binary + is classifies as numeric context.

      Indeed that would have been right part to explain the difference re what happens when you uncomment the line with the binary +: in fact it's the one quoted by the author of the original article. (But I didn't want to repeat). However the one I emphasized did apply to what I was discussing around that point i.e. why ++($f='z') is 'aa' and ++($f='9') is 10.

Re: A somewhat unexpected side effect... (stringy)
by tye (Sage) on Nov 21, 2006 at 16:06 UTC

    I'm not sure I understood the last half of your node, but, no, you don't get an "ordinary" increment just because a scalar looks like a number. But it can be hard to distinguish an ordinary (numeric) increment from a magic (stringy) increment in such a case. But here are a couple of examples that demonstrate the difference:

    #!/usr/bin/perl -w use strict; my $n= '009'; $n++; print $n, $/; print 0+$n, $/; print $n, $/; $n++; print $n, $/; $n= join '', (1..9,0)x7; $n++; print $n, $/; print 0+$n, $/; print $n, $/; my $p= $n; $n++; print $n, $/; print $n-$p, $/;

    which produces (minus the comments, of course):

    010 # magic increment preserves leading zeros 10 # treating it as a number doesn't give leading zeros 010 # but doesn't strip them from the scalar 11 # but the next increment is numeric not stringy # stringy increment can deal with /any/ number of digits: 1234567890123456789012345678901234567890123456789012345678901234567891 # numbers only have about 20 significant digits: 1.23456789012346e+069 # treating as a number doesn't destroy the string: 1234567890123456789012345678901234567890123456789012345678901234567891 # but the next increment is just numeric 1.23456789012346e+069 0 # and adding 1 to 1e69 does nothing

    Hope that helps.

    - tye        

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://585235]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-04-23 23:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found