Joe Smith on Wed, 26 Apr 2000 01:51:31 -0400 (EDT)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Perl 5.6 question


On Tue, Apr 25, 2000 at 07:16:25PM -0400, Kurt D. Starsinic wrote:
> On Tue, Apr 25, 2000 at 07:02:02PM -0400, Joe Smith wrote:
> > On Tue, Apr 25, 2000 at 03:58:58PM -0400, mjd-perl-pm@plover.com wrote:
> > > 
> > > > Perl 5.6 question: Why would you want to use an lvalue sub?
> > > 
... snip ...
> > What does this look like in the method?  Is it as simple as
> > 
> >   sub color:lvalue { $_[0]->{'_color'} }
> > 
> > Can subs be marked :'lvalue' dynamically, so AUTOLOAD can whip up such
> > nifty attribute accessors on-the-fly?
> > 
> > Is it easy to code something that still accepts a new value as an
> > argument, for compatibility?
> > 
> >   sub color:lvalue { @_ > 1 ? $_[0]->{'_color'} = $_[1] : $_[0]->{'_color'} }
> 
>     These all sound like great research questions.  Why don't you
> download and install 5.6, try some things, and let us all know what
> you think?  Is it usable, intuitive, fast?  Practical experience always
> beats abstract speculation, in my book.

Well call my bluff why don't ya?

The same silly thought occurred to me, and I figured some penitent
self-flagellation compiling and installing a large Unix source package
would do me a world of good, so...

The answers (to the questions I asked) are 'yes', 'yes' and 'yes'.

You can simply do sub AUTOLOAD : lvalue { ... } and it works: as long
as it returns an lvalue, all is well.

You can declare an anonymous sub 'lvalue' also:

   $model = sub : lvalue { $_[0]->{'_model'} };

However, calling it through an object crashes Perl:

   $car->$model = 'coupe';

   panic: unexpected optree near method call ...
   Execution of ./lvsub.perl aborted due to compilation errors.

Calling it as a straight sub is cool:

   &$model($car) = 'coupe';
or
   $model->($car) = 'coupe';
   
One major difference I noticed: hash element lvalues autovivify, hash
elements assigned to through a sub don't.
   
   $car = bless {};

   sub color:lvalue { $_[0]->{'_color'} }

   $car->{'_model'} = 'coupe'; # ok, $car->{'_model'} is automatically created

   $car->color = 'blue'        # bad dog!

   Can't return a readonly value from lvalue subroutine ...

The error message is a little confusing: the 'readonly value' is
'undef', because $car->{'_color'} doesn't exist.

Not a big deal; just make sure all the object's attributes are
initialized when it's created.  Safer not to depend on autovivifi-
cation anyway.

For now, according to the perlsub doc, the lvalue is restricted to
scalars.  You can't have an lvalue sub that returns an array or hash
to be assigned to.

I didn't do any benchmarks, but so far it looks quite usable.

<Joe
**Majordomo list services provided by PANIX <URL:http://www.panix.com>**
**To Unsubscribe, send "unsubscribe phl" to majordomo@lists.pm.org**