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
>>>> ==========================*/
>>>>
>>>>
>>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.