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




Reply via email to