Edit: Please see below for the solution.

O monks,

My program has a loop in which it instantiates a Moo object and composes in one or another role based on some condition.

Debugging shows that each time through the loop a new object is instantiated, and the correct role is composed in, but when I call a method on the object, the first object's method gets the call! Even though it is a new instance of the object and the old one has gone out of scope since we are in the next iteration of the loop.

It's acting as if the method is compiled into memory. I feel like this is so weird it *must* be something simple I'm overlooking, but I can't for the life of me see what. Any help to understand would be greatly appreciated.

Here's code that demonstrates the issue: MyClass.pm :

package MyClass; use Moo; sub BUILD { my ( $self, $args ) = @_; my $module = $args->{'number'} % 2 ? 'Odd' : 'Even'; warn "$args->{'number'} $self loading $module"; eval "with '$module'; 1;" or die $@; } 1;
Odd.pm :
package Odd; use Moo::Role; warn "Loaded ", __PACKAGE__; sub bar { my ( $self, $foo ) = @_; warn "$foo $self I am Odd"; } 1;
Even.pm :
package Even; use Moo::Role; warn "Loaded ", __PACKAGE__; sub bar { my ( $self, $foo ) = @_; warn "$foo $self I am Even"; } 1;
test.pl :
#!usr/bin/perl use strict; use warnings; use MyClass; foreach my $foo ( 1 .. 2 ) { print "\n"; my $o = MyClass->new({ number => $foo }); warn "$foo $o->bar"; $o->bar( $foo ); print "\n"; } __END__
Output, NOT as expected. Note the object memory address is different second time through, and the correct module is loaded, but the sub that gets called is from the other package!
$ perl test.pl 1 MyClass=HASH(0x118df00) loading Odd at MyClass.pm line 8. Loaded Odd at Odd.pm line 4. 1 MyClass=HASH(0x118df00)->bar at test.pl line 13. 1 MyClass=HASH(0x118df00) I am Odd at Odd.pm line 7. 2 MyClass=HASH(0x11b68e8) loading Even at MyClass.pm line 8. Loaded Even at Even.pm line 4. 2 MyClass=HASH(0x11b68e8)->bar at test.pl line 13. 2 MyClass=HASH(0x11b68e8) I am Odd at Odd.pm line 7.

Thank you!

Note: this post was edited, including title, to remove extraneous references to Parallel::ForkManager which I thought was the issue. Thanks to Athanasius for pointing out that that was unrelated. )

EDIT: thanks to a push from Athanasius and a giant assist from mst on IRC, I figured out the correct way to do what I want, which is to use Role::Tiny->create_class_with_roles to compose the Role into an anonymous class before calling new().

So now MyClass.pm looks like:

package MyClass; use Moo; 1;
and the caller looks like:
#!usr/bin/perl use strict; use warnings; use MyClass; use Role::Tiny(); foreach my $foo ( 1 .. 2 ) { my $module = $foo % 2 ? 'Odd' : 'Even'; my $class = Role::Tiny->create_class_with_roles( 'MyClass', $modul +e ); my $o = $class->new(); $o->bar( $foo ); } __END__
Output:
$ perl test.pl 1 MyClass__WITH__Odd=HASH(0x23f5f80) I am Odd at Odd.pm line 8. 2 MyClass__WITH__Even=HASH(0x2442db0) I am Even at Even.pm line 7.


The way forward always starts with a minimal test.

In reply to SOLVED [ create_class_with_roles() ]: Moo[se] namespace weirdness with conditionally composed-in Roles by 1nickt

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.