in reply to Uses for an lvalue subroutine

sub Foo::address : lvalue { my $self = shift; $self->{address} }; ... my $f = Foo::new; $f->address = "123 main street"; print $f->address;

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
Re^2: Uses for an lvalue subroutine
by tadman (Prior) on Jan 10, 2001 at 07:46 UTC
    Oh, the joys of lvalue!
        package Object;
    
        use vars '$AUTOLOAD';
    
        # :
    
        sub AUTOLOAD : lvalue
        {
                my ($self) = shift;
    
                $AUTOLOAD =~ s/.*://;
    
                @_? $self->{$AUTOLOAD} = shift : $self->{$AUTOLOAD} ||= undef;
        }
    
    Sweet candy. Now you can do stuff like this:
         my ($object) = new Object;
    
         $object->whatever = "Data";
         print "Whatever is '",$object->whatever,"'\n";
    
    It "goes both ways" as an LVALUE, and this AUTOLOAD routine has backwards compatibility with the older, somesay wacky function method:
         my ($object) = new Object;
    
         $object->whatever("Data");
         print "Whatever is '",$object->whatever(),"'\n";
    
    You even get warnings with perl -w if you use uninitialized members.
      That's twisted and clever. One question: what is the intent of the ||= undef, other than changing $self->{$AUTOLOAD} to undef if it's 0 or ""?
      my ($object) = new Object; $object->whatever(0); print "Whatever is '",$object->whatever(),"'\n"; # Oops!
        chipmunk points out something that I had failed to test for. In my effort to reduce the code down to a minimum, that case slipped right through my logic. Here's Take II, new and improved support for 0 and "" added:
        
        sub AUTOLOAD : lvalue
        {
                my ($self) = shift;
        
                $AUTOLOAD =~ s/.*://;
        
                @_?
                        $self->{$AUTOLOAD} = shift 
                        : !defined($self->{$AUTOLOAD})?
                                $self->{$AUTOLOAD} = undef 
                                : $self->{$AUTOLOAD};
        }
        
        
        The reason for having $self->{$AUTOLOAD} = undef is to give the caller something to assign to. Returning an invalid hash entry will cause an assignment error. 'undef' is not a valid lvalue, but returning a reference to a variable which may have a value of 'undef' is acceptable.

        BTW, I've never had to indent my '?:'s before, but it was the only way to make how this worked clear(er).
Re: Re: Uses for an lvalue subroutine
by shotgunefx (Parson) on Jun 04, 2002 at 23:49 UTC
    Good example, but I think you mean shift   :P

    -Lee

    "To be civilized is to deny one's nature."