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