http://www.perlmonks.org?node_id=222969


in reply to $foo->bar = 14;

I had similar ideas regarding lvalue subs for accessor/mutator methods (see: (my?) problem with re-blessed references(?)), and I still find the idea appealing. The limitations of the current experimental implementation of lvalue subs render them such that for anything other than trivial cases, the limitations outway the benefits currently.

As I described in What the [sub]in 'L value do they have?, I thought I saw ways to improve the current implementation, but it may be that doing so would limit or corrupt their existing utility.

I haven't yet managed to wrap my head around how the sub could be given access to the assigned value in

 $foo->bar =~ s/a/b/g;

prior to assignment, without destroying the efficiency and utility of that construct.

One thought that does come to mind is that lvalue accessor/mutator methods could be used internally to a class for accessing their own instance data in true OO-style, but that the published interface would not expose those methods. This would retain the benefits of minimising changes within the class if the structure of the instance data changed, but would also remove some of the overhead in having non-mutator methods access instance data via them.

I just re-read that and whilst it says what I am trying to say, it's about as clear as mud and I don't see how to easily improve it. Perhaps a simple example.

#! perl -slw use strict; package Message; use constant CLASS => 0; use constant SELF => 0; use constant TEXT => 1; use constant TS => 1; use constant ATTRIBUTES => qw/_id _timestamp text/; BEGIN { no strict 'refs'; for my $property (ATTRIBUTES){ *$property = sub : lvalue { $_[SELF]->{$property}; } } } { my $nextID = 0; sub new { my $self = {}; @$self{'_id', '_timestamp', 'text'} = ($nextID++, time(), $_[T +EXT] || 'Unassigned!'); return bless $self, $_[CLASS]; } } sub ID { $_[SELF]->_id; } sub timeStamp { $_[SELF]->_timestamp } sub setTS { $_[SELF]->_timestamp = $_[TS] if $_[TS] and $_[TS] =~ /^\d ++/; } sub stringify{ sprintf '<' . __PACKAGE__ . '>' . $/ . '<id value="%04d" />' . $/ . '<timestamp value="%010d" />' . $/ . '<message-text>%s</message-text>' . $/ . '</' . __PACKAGE__ . '>' . $/, map{ $_[SELF]->$_ } ATTRIBUTES; } package main; my $msg = new Message 'A message'; print $msg->stringify(); $msg->text = 'This is the new message text'; print $msg->timeStamp; $msg->setTS( time()-1000 ); print $msg->stringify(); my $msg2 = new Message; print $msg2->stringify(); $msg2->text = 'Yet another test message'; print $msg2->stringify(); __END__ C:\test>lvalue <Message> <id value="0000" /> <timestamp value="1041200593" /> <message-text>A message</message-text></Message> 1041200593 <Message> <id value="0000" /> <timestamp value="1041199593" /> <message-text>This is the new message text</message-text></Message> <Message> <id value="0001" /> <timestamp value="1041200593" /> <message-text>Unassigned!</message-text> </Message> <Message> <id value="0001" /> <timestamp value="1041200593" /> <message-text>Yet another test message</message-text> </Message>


Examine what is said, not who speaks.