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
> > > ==========================*/
> > >
> > >
>

Reply via email to