Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Strange behavior: passing $1 to AUTOLOAD

by johnnywang (Priest)
on Sep 22, 2004 at 22:03 UTC ( [id://393062]=perlquestion: print w/replies, xml ) Need Help??

johnnywang has asked for the wisdom of the Perl Monks concerning the following question:

I'm having a hard time understand this behavior (the title is probably not accurate). The Person class below is copied exactly from the CookBook, if I pass a literal parameter, all is fine, but if I pass $1 from a regex, then it got lost. What's going on?
use strict; use Person; my $person1 = Person->new; $person1->name("goodname"); # pass a string literal print "Good name: ", $person1->name(),"\n"; # the name is printed. my $person2 = Person->new; my $s = "badname"; if($s =~ /(.+)/){ #just to match anything $person2->name($1); # now pass $1, which is "badname" } print "Bad name:",$person2->name(),"\n"; # the name is lost! __END__ Good name: goodname Bad name:
Here's the person class from the Cookbook:
package Person; use strict; use Carp; use vars qw($AUTOLOAD %ok_field); # Authorize four attribute fields for my $attr ( qw(name age peers parent) ) { $ok_field{$attr}++; } sub AUTOLOAD { my $self = shift; my $attr = $AUTOLOAD; $attr =~ s/.*:://; return unless $attr =~ /[^A-Z]/; # skip DESTROY and all-cap metho +ds croak "invalid attribute method: ->$attr()" unless $ok_field{$attr +}; $self->{uc $attr} = shift if @_; return $self->{uc $attr}; } sub new { my $proto = shift; my $class = ref($proto) || $proto; my $parent = ref($proto) && $proto; my $self = {}; bless($self, $class); $self->parent($parent); return $self; } 1;

Replies are listed 'Best First'.
Re: Strange behavior: passing $1 to AUTOLOAD
by diotalevi (Canon) on Sep 22, 2004 at 22:29 UTC
    $1 was cleared when you executed $attr =~ s/.*:://;. Change your AUTOLOAD so it copies the value out before clobbering the regexp value.
      Thanks. But what is the general rule here? a sub needs to always make a copy of the parameters if it uses regex?
        The general rule is never, ever pass in $1 and its friends, as they're terribly ephemeral. Make copies and pass them in instead.

        As Elian says, make copies when passing in ephemeral values such as $1, $!, $@; one easy way to do that is to stringify, as long as that doesn't lose you information:

        $person->name("$1");

        If just the string is not enough (eg to pass the dualvar $!), I think the easiest way is to make a copy:

        my $error = $!; $log->error($error);

        Hugo

        Function parameters are passed by reference. This means @_ contained $1 which is modified by any successful regex. You can modify values in @_ directly to watch this.

        Most of the time you aren't passing something like $1 in and don't have to worry about the issue you ran into

Re: Strange behavior: passing $1 to AUTOLOAD
by ikegami (Patriarch) on Sep 23, 2004 at 00:11 UTC
    In general terms, it's a bad idea to expect $_ and $1 and similar to survive a function call, as explained above. It's best to save the value of these (in a my variable) before calling a function if you intend of reusing the value.
Re: Strange behavior: passing $1 to AUTOLOAD
by Cody Pendant (Prior) on Sep 23, 2004 at 06:16 UTC
    May I just ask which "Cookbook" is referred to here, out of interest?


    ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
    =~y~b-v~a-z~s; print
      "Perl Cookbook", by Tom Christiansen and Nathan Torkington, from O'reilly. I was refering to 1st edition, section 13.11

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://393062]
Approved by chromatic
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2024-04-19 19:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found