in reply to Re: Uses for an lvalue subroutine
in thread Uses for an lvalue subroutine

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.

Replies are listed 'Best First'.
Re: Re: Re: Uses for an lvalue subroutine
by chipmunk (Parson) on Jan 10, 2001 at 09:02 UTC
    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).