SPUG: Switch's "case" matching doesn't set $1 !
Tim Maher
tim at consultix-inc.com
Tue Feb 13 11:56:40 PST 2007
On Tue, Feb 13, 2007 at 11:13:13AM -0800, Eric Wilhelm wrote:
> # from Tim Maher
> # on Tuesday 13 February 2007 10:48 am:
>
> > What's more, the docs characterize the
> >"case /re/" syntax as "match if $s =~ /$c/", suggesting that any
> >regex valid in a real matching operator should be usable.
>
> Try dumping the filtered source.
>
> perl -MO=Deparse script
>
> There, you'll see that it is indeed the "if/elsif/elsif/else" lexical
> structure that you might expect from the input structure, but rather
> than doing "$_ =~ m/.../" in the if(), it ships the regexp off to the
> case() function
... which, AFAICT (see below), then does the "$_ =~ m/.../"
> Had it been implemented as a DSL of prototyped functions (sub case ($&)
> {...}, then the capture might work because your code would get executed
> within scope of the match.
>
> --Eric
To produce the effect I'm expecting, it's not necessary for the
match to be executed within the scope of the user's code--just
for the match to be left in $1--which, as part of the package
"main", is always in scope.
The relevant chunk of code in the module (switching on scalar, doing
regexp match), seems to be this (>>) one:
elsif ($s_ref eq "") # STRING SCALAR
{
$::_S_W_I_T_C_H =
sub { my $c_val = $_[0];
my $c_ref = ref $c_val;
return $s_val eq $c_val if $c_ref eq "";
return in([$s_val],$c_val) if $c_ref eq 'ARRAY';
return $c_val->($s_val) if $c_ref eq 'CODE';
return $c_val->call($s_val) if $c_ref eq 'Switch';
>>>>>>>>>> return scalar $s_val=~/$c_val/
>>>>>>>>>> if $c_ref eq 'Regexp';
return scalar $c_val->{$s_val}
if $c_ref eq 'HASH';
return;
};
}
This program demonstrates that () symbols can be recognized when
delivered via variables:
perl -wle '$re=".(.)."; "abc" =~ /$re/ and print $1' # prints: b
By the same token (pun intended), I'd expect the following code to
produce a usable $1--unless the module localizes $1, which would
prevent that result, but it doesn't seem to do that (Damian !~ /dumb/)
($1 is part of the package "main", and therefore always in scope.)
for ('chocolate', 'vanilla', 'swirl') {
switch($_) {
case /(vanilla|chocolate)/ { # () sets $1 ??
print "The flavor of the moment is: $1"; # what's $1?
}
else {
print "'$_' is not a real flavor!";
}
}
}
$ perl script
The flavor of the moment is: unset
The flavor of the moment is: unset
'swirl' is not a real flavor!
*-------------------------------------------------------------------*
| Tim Maher, PhD (206) 781-UNIX http://www.consultix-inc.com |
| tim at ( Consultix-Inc, TeachMePerl, or TeachMeUnix ) dot Com |
| Classes: 2/28: Basic Perl; 3/12: Basic UNIX/Linux; 3/16: Min Perl |
*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-*
| * "Minimal Perl" book rates 4.8 out of 5 stars at Amazon.com! * |
| > Download chapters, read reviews, and order at MinimalPerl.com < |
*-------------------------------------------------------------------*
More information about the spug-list
mailing list