Re: Moose Question
[email protected] (Stevan Little)
| Newsgroups | perl.moose |
|---|---|
| Message-ID | <[email protected]> |
Christopher,
I am not sure I am understanding the error you are describing. Could
you write up a small failing test for me?
Thanks,
- Stevan
On Mar 27, 2008, at 3:09 PM, Christopher Brown wrote:
> Paul and Stevan,
>
> Sorry for the late reply. Thanks for both answers. Stevan, I am rely
> impressed with the rapidity of which you and the other Moose members
> respond. I am also impressed with you presenting a working
> prototype of my
> problem in as little time and code as you did. It is really a
> testament to
> Moose's power.
>
> In the end, I went with the solution that Paul offered. That is, *
> create_anon_class()->rebless_instance*. And, I have used this
> recipe a
> half-dozen or times since. It is really powerful technique for
> installing
> instance methods. I did run into a snag with reblessing
> instances. It
> seems that I cannot access the meta object after reblessing. I am
> not so
> sure why I have the following work on the reblessed object:
>
> $self->meta->add_method( 'test', sub { say "Hello World" } );
> # $self
> is the reblessed self.
>
> Interestingly enough, the method does not produce an error.
>
> As I am discovering with Moose, there is probably a real simple and
> elegant
> solutions of which has eluded me. As always, your help is greatly
> appreciated.
>
> Best,
>
> Chris
>
>
>
>
>
>
> On Thu, Mar 20, 2008 at 8:22 AM, Paul Driver <[email protected]>
> wrote:
>
>> Chris,
>>
>> If you want to add generated methods to the class, it's
>> __PACKAGE__->meta->add_method(foobar => sub { print "Foo, bar!
>> \n" }); I
>> don't think you want to do this in BUILD though - just at class
>> compile
>> time. I do this a lot when I have a bunch of similar methods and
>> don't want
>> to repeat myself.
>>
>> If you want to add methods to a particular instance ONLY, the
>> thing to do
>> is to create an anonymous subclass and rebless your instance to that
>> subclass, and add the methods to the subclass.
>>
>> Some example code - at BUILD time, add a method named $word that
>> does say
>> $word for every word passed into the constructor.
>>
>> ---
>>
>> use feature q(say);
>> package Speaker;
>> use Moose;
>>
>> has words => (
>> is => 'ro',
>> isa => 'ArrayRef[Str]',
>> predicate => 'has_words',
>> );
>>
>> # All Speakers know how to say bar
>> sub bar {
>> say 'bar';
>> }
>>
>> sub BUILD {
>> my ($self, $args) = @_;
>> if ($self->has_words) {
>> my %methods = map {
>> my $word = $_;
>> ($word => sub { say $word})
>> } @{$self->words};
>>
>> $self->meta->create_anon_class(
>> superclasses => [__PACKAGE__],
>> methods => \%methods,
>> )->rebless_instance($self);
>> }
>> }
>>
>> package main;
>> my $a = Speaker->new;
>> my $b = Speaker->new(words => [qw(baz qux)]);
>> $a->bar; # => "Bar"
>> $b->bar; # => "Bar"
>> $b->qux; # => "Qux"
>> say "A" if $a->isa('Speaker'); # => "A"
>> say "B" if $b->isa('Speaker'); # => "B"
>> $a->qux; # Can't locate method "qux" via class "Speaker"
>>
>> ----
>>
>>
>> On Mar 19, 2008, at 4:22 PM, Christopher Brown wrote:
>>
>> Dave,
>>>
>>> Sorry for taking so long to thank you for your reply. Thanks. On
>>> further
>>> t, it was a silly question, using a plain old method is obviously
>>> the
>>> solution.
>>>
>>> I do have follow-up questions, though. Suppose I want to
>>> generate those
>>> plain old methods dynamically. Is there a simple, moose way to
>>> do this
>>> in
>>> the BUILD subroutine. On e way to accomplish this is to assign an
>>> anonymous subroutine to a glob. Like this:
>>>
>>> package My::App;
>>>
>>> use Moose;
>>> has name => ( is => 'rw', isa=>'Str' );
>>>
>>> sub BUILD {
>>> **__PACKAGE__::method = sub { print "hello world\n"; } ;*
>>> }
>>>
>>> package main;
>>> my $app = My::App->new( { name => 'Moose' } );
>>> $app->method;
>>>
>>>
>>> But I don't want to do that. I want to do it the Moose way.
>>>
>>> I can hear you ask, but why would you want to do that? Well
>>> suppose, I
>>> create an object that wraps a query. If I can iterate over the
>>> record
>>> set I
>>> can replace the data slot with the new record and still named
>>> methods
>>> that
>>> act as accessors to the record. This beats the snot out of
>>> trying to
>>> instanciate a row object for each record.
>>>
>>> Thanks in Advance,
>>>
>>> Chris
>>>
>>>
>>>
>>>
>>>
>>> On Wed, Mar 12, 2008 at 2:41 PM, Dave Rolsky <[email protected]>
>>> wrote:
>>>
>>> On Wed, 12 Mar 2008, Christopher Brown wrote:
>>>>
>>>> Despite the 'lazy' evaluation, it appears as if the attribute
>>>> value
>>>>> is
>>>>>
>>>> being
>>>>
>>>>> cached instead of being re-evaluated when the accessor is being
>>>>> called.
>>>>>
>>>>
>>>> Lazy just means "don't generate the attribute from the default sub
>>>> until
>>>> the _first_ time it is requested". It's still cached.
>>>>
>>>> If you want to return a different value each time then you just
>>>> want a
>>>> plain old method, not an attribute.
>>>>
>>>>
>>>> -dave
>>>>
>>>> /*==========================
>>>> VegGuide.Org
>>>> Your guide to all that's veg
>>>> ==========================*/
>>>>
>>>>
>>