Consideration of the way Perl converts a string to a number is interesting, but I was puzzled by why all the other things that are done to $N in TEST() seem to have no effect. Here's the narrative I've imagined for the critical part of what's happening:
-
In the $N += 0; statement, the number 0 is added to the string $N (after its conversion to a temporary number according to the rules already discussed in this thread) to generate a number that is assigned to a temporary, intermediate variable, but not yet to $N.
-
In the course of numifying the string and adding, the "... isn't numeric in addition ..." warning is triggered, and this is trapped by the local $SIG{__WARN__} = sub { ... } handler temporarily installed by TEST().
-
The $SIG{__WARN__} handler assigns a lot of stuff to $N and prints a lot of stuff, but none of it makes any difference because...
-
When the $N += 0; statement completes, it assigns the contents of its temporary, intermediate variable to $N and that's all, folks; any changes to $N prior to this final assignment are wiped out.
Here's the code I used to convince myself of the validity of this narrative:
c:\@Work\Perl\monks>perl
use strict;
use warnings;
sub TEST {
defined $_[0] or return 0;
my $N = shift;
printf "TEST('$N') called - ";
local $SIG{__WARN__} = sub {
# doing anything or nothing to $N has no effect here
# return; # try this
printf "(in warn '$N' -> ";
$N =~ tr|0-9||cd;
$N = "0$N";
$N = 'garbage';
printf "'$N') - ";
};
printf "\$N is '$N' before += - ";
$N += 0;
printf "\$N is '$N' after += \n";
return int($N);
}
for my $n (qw(55 55x x55)) {
my $m = TEST($n);
print "TEST('$n') returns $m \n\n";
}
__END__
TEST('55') called - $N is '55' before += - $N is '55' after +=
TEST('55') returns 55
TEST('55x') called - $N is '55x' before += - (in warn '55x' -> 'garbag
+e') - $N is '55' after +=
TEST('55x') returns 55
TEST('x55') called - $N is 'x55' before += - (in warn 'x55' -> 'garbag
+e') - $N is '0' after +=
TEST('x55') returns 0
I guess an opcode decompilation could confirm my conjecture, but I'm too lazy to do this right now.
Update: Re-writing the $N += 0; statement as $N = $N + 0; may allow better visualization of what I think happens: The $N + 0 expression must be evaluated first, and it's in this evaluation that the warning is triggered and a bunch of irrelevant things are done to $N; then the $N = ...; assignment is done, overwriting any changes to $N made by the $SIG{__WARN__} handler.
Give a man a fish: <%-{-{-{-<
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.
|