|
Posted by Dodger on May 6, 2008, 6:53 am
Please log in for more thread options
I decided I wanted to see if I could reproduce the effects of some
pretty common code in Perl. For instance, the Ruby version:
class Book
attr_reader :title
attr_accessor :price
def initialize(title, price)
@title, @price = title, price
end
end
or more verbosely in Ruby:
class Book
def initialize(title, price)
@title, @price = title, price
end
def title
@title
end
def price
@price
end
def price=(price)
@price = price
end
end
This is basically a case of price being a public property and title
being a protected one (i.e. only a read, no accessor).
So it seemed that with all the things Perl can do I should have been
able to do the same thing in Perl, right? Maybe with a little
finagling, but it hsould be possible.
I came up with this code:
package Book;
use strict;
our $AUTOLOAD;
sub new($$$) {
my $class = shift;
my $self = {};
$self->-> = [qw(title)];
$self-> = undef;
bless $self, ref $class || $class;
$self-> = shift;
$self-> = shift;
return $self;
}
sub AUTOLOAD : lvalue {
my $self = shift;
my $property = $AUTOLOAD;
$property =~ s/.*://;
if (exists $self->) {
if (grep $property eq $_, @->}) {
warn "$property is Protected\n";
my $val = $self->;
return $val;
}
$self->;
}
else {
$self->;
}
}
Problem is, it doesn't work...
This code calling it dies at the second (price, the public one)
assignment attempt:
print "Title read: ", $book->title, "\n";
print "Price read: ", $book->price, "\n\n";
print "Title modify: ", $book->title = "Hello", "\n";
print "Price modify: ", $book->price = 5, "\n\n";
title is Protected
Title read: The Moon is a Harsh Mistress
Price read: 7.99
title is Protected
Title modify: Hello
Can't return a temporary from lvalue subroutine at lv.pl line 10.
Now, you aren't supposed to use return in an lvaluable subroutine, of
course... however, if I DON'T use a return, I get the error. And if I
do use return, the lvalue doesn't modify the actual thing.
Is there away around this? Can I make this work?
Granted, it's all for my own 'personal enrichment', not for any real
use or anything... still, I don't like the idea that I can't make
something work...
--
Sean 'Dodger' Cannon
|
|
Posted by Dodger on May 6, 2008, 7:13 am
Please log in for more thread options
On May 6, 3:53 am, I wrote:
> I decided I wanted to see if I could reproduce the effects of some
> pretty common code in Perl. For instance, the Ruby version:
> ...
> Is there away around this? Can I make this work?
BTW, I know of course I can easily do it without AUTOLOAD:
sub new($$$) {
my $class = shift;
my $self = {};
$self->-> = [qw(title)];
$self-> = undef;
bless $self, ref $class || $class;
$self-> = shift;
$self-> = shift;
return $self;
}
sub title {
shift->;
}
sub price : lvalue {
shift->;
}
That works fine. However, it seemed so strongly that I should be able
to do it with AUTOLOAD too...
--
Sean 'Dodger' Cannon
|
|
Posted by Darin McBride on May 6, 2008, 9:55 am
Please log in for more thread options Dodger wrote:
> So it seemed that with all the things Perl can do I should have been
> able to do the same thing in Perl, right? Maybe with a little
> finagling, but it hsould be possible.
Take a look at Contextual::Return. It may provide enough syntactical sugar
to make this easy.
Rough guess, untested:
sub _any(&@) { my $s = shift; $s->() && return 1 for @_; return; }
sub AUTOLOAD :lvalue {
my $self = shift;
my ($property) = $AUTOLOAD) =~ /::([^:]+)$/;
if (_any { $property eq $_ }, @}) {
return RVALUE { $self-> }
LVALUE { require Carp; croak "Can't use $property as lvalue" }
}
$self->
}
Or something like that.
|
|