Practically any other use of $2 would have resulted in the uninitialized value warning. And shouldn't it do so here? I mean, this code raises the warning:#!/usr/bin/perl -w "abcde" =~ /(..)(?:(....)|(..))/; # $1 is 'ab' # $2 is undef # $3 is 'cd' print length($2);
So why not with $2? The answer lies in the fact that the digit variables (and I think all punctuation variables) are magical, and as such their accesses are controlled by internal (C) functions. Specifically, length($2) calls the C function Perl_magic_len() (found in mg.c).#!/usr/bin/perl -w print length($foo);
Examination of this function shows that variables which don't meet criteria to return a non-zero length end up falling through the cracks (intentionally) of the switch() statement, and end up returning 0. There's no code for raising a "use of uninitialized value" warning.
Why, you ask, does Perl_magic_len() not determine the length of the string returned from Perl_magic_get() (which governs fetching the variable's value)? Or, why doesn't length($2) call Perl's standard length() function with the value of $2? Because the variable is magic, and all of Perl's built-in functions (on the source-code level) have handles dealing with magic variables.
NB: one thing that irks me is that tied scalars do not have a LENGTH() method. Por que, Señor?When length() encounters a magic variable as its argument, it calls that magic variable's length function. Normal scalars contain their length information as part of themselves (the SV structures in the C code). Magic variables are a completely different story. Chances are they don't actually hold any data at all. $2 gets its length from the source-code equivalent of the @- and @+ arrays, rx->startp[idx] and rx->endp[idx].
Paraphrasing the source code, when you ask for the length of $2, Perl does the following:
There's some added work for UTF8 in there, but I don't give a hoot./* n is the number in $N */ if ( (n <= rx->nparens) && (s = rx->startp[n]) != -1 && /* -1 => not there */ (e = rx->endp[n]) != -1 ) return e - s; return 0;
There's your source-diving lesson for the day. I might do this from time to time, and not on topics as esoteric as this.
_____________________________________________________
Jeff[japhy]Pinyan:
Perl,
regex,
and perl
hacker.
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;
|
|---|