(tye)Re: Uses for an lvalue subroutine
by tye (Sage) on Jan 10, 2001 at 04:07 UTC
|
As merlyn demonstrated but didn't explain, the lvalue
attribute for subroutines was mainly (from my perspective)
motivated by the desire to have more traditional object
members rather than force the writing of get/set methods
for each member.
-
tye
(but my friends call me "Tye")
| [reply] |
|
|
But if object method returns lvalue, it cannot be effectively overriden by subclasses to do something else.
Example:
package SuperClass;
sub foo :lvalue { my $self = shift; $self->{foo} }
package SubClass;
@ISA=qw(SuperClass);
sub foo :lvalue {
# Now I want to store value of foo attribute in RDBMS,
# how can I do that?
}
In this context, lvalue object methods are very dangerous,
because they limit flexibility of objects. | [reply] [d/l] |
|
|
You use $self->{foo}, of course.
When using inheritance, you don't treat your ancestors as black boxes (well, if you are doing inheritance of APIs, then you do, but Perl doesn't natively support inheritance of APIs anyway).
Of course, if the SuperClass::foo() is very complex or you just want to write an inefficient subclass, then you can use $self->SUPER::foo() instead.
So using :lvalue methods in a class doesn't really change anything about inheritance.
-
tye
(but my friends call me "Tye")
| [reply] [d/l] [select] |
|
|
|
|
|
|
Return a tied object as an lvalue. Here's a quick sample using a DBM:
dbmopen %FOO, "my_database", 0644 or die;
...
sub foo :lvalue {
my $self = shift;
$FOO{$self->key};
}
...
my $obj = SubClass->new;
$obj->foo = 35; # calls tied(%FOO)->STORE($obj->key, 35);
my $fetch = $obj->foo; # calls tied(%FOO)->FETCH($obj->key);
Change the tie package as needed.
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] |
|
|
|
|
My Second Edition Camel book appears to have no mention of this feature... is it new to Perl 5.6, or just one of those details left out of the Camel? I suppose that the third possibility would be that it is in the Camel and I was too dumb to notice, but let's not talk about that.
It looks pretty darn useful though, as merlyn illustrated... I'm surprised that I've never heard of it before.
Hot Pastrami
| [reply] |
|
|
| [reply] |
Re: Uses for an lvalue subroutine
by merlyn (Sage) on Jan 10, 2001 at 04:01 UTC
|
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 | [reply] [d/l] |
|
|
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.
| [reply] [d/l] |
|
|
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!
| [reply] [d/l] [select] |
|
|
|
|
Good example, but I think you mean shift :P
-Lee
"To be civilized is to deny one's nature."
| [reply] |
Re: Uses for an lvalue subroutine
by lemming (Priest) on Jan 10, 2001 at 04:03 UTC
|
You may want to look at substr for an example to start with. | [reply] |