develooper Front page | perl.moose | Postings from February 2015

Re: incomplete role consumption?

Thread Previous | Thread Next
From:
Gianni Ceccarelli
Date:
February 25, 2015 22:26
Subject:
Re: incomplete role consumption?
Message ID:
20150225222616.729cd248@nautilus
Short version: you have a dependency loop, and your code, as written,
can not work.

Longer version: main.pl loads Test1, which loads TestRole, which loads
TestGlue, which loads Test1. Boom!

On 2015-02-25 Daniel Hermann <daniel.hermann@1und1.de> wrote:
> The above code works if
> 
> - I do not 'use Test2' in TestGlue.pm or

This removes half the dependency loop, and (by accident) makes the
whole thing work. But if you change the order of the "use" in main, it
will fail for Test1

> - I use an eval block in main.pl such as
> 
>      eval { use Test2; Test2->new->load; };

In which case Test2 is loaded after all the compilation, and again you
have half-removed the loop. Again, this is still fragile.

> It seems to me that the import of the class Test2 in "role context"
> via TestGlue.pm, triggered by 'use Test1' in main.pl, is incomplete
> somehow, and the second import via 'use Test2' in main.pl does
> not compensate this.

Detailed explanation:

a "use Foo" statement is (roughly) equivalent to a "BEGIN { require
Foo }". "require", as documented in perlfun, uses the global %INC to
avoid loading a file more than once. Each entry in %INC is set
optimistically, before actually loading the corresponding file. So the
sequence in your case is:

1) main.pl is compiled, %INC is empty
2) "use Test1" is compiled and executed, $INC{'Test1.pm'}='Test1.pm'
3) Test1 loads Moose, $INC{'Moose.pm'}='/path/to/Moose.pm'
4) Test1 finishes compiling
5) Test1 is run (still inside the BEGIN block generated by the "use
   Test1" in main)
6) "with 'TestRole'" causes a "require TestRole"
7) TestRole is loaded, $INC{'TestRole.pm'}='TestRole.pm'
8) TestRole loads Moose::Role,
   $INC{'Moose/Role.pm'}='/path/to/Moose/Role.pm'
9) TestRole loads TestGlue
10) TestGlue is loaded, $INC{'TestGlue.pm'}='TestGlue.pm'
11) TestGlue uses Moose, but $INC{'Moose.pm'} is true, no loading
    happens
12) TestGlue uses Test1, but $INC{'Test1.pm'} is true, no loading
    happens
13) TestGlue uses Test2
14) Test2 is loaded, $INC{'Test2.pm'}='Test2.pm'
15) Test2 loads Moose, but $INC{'Moose.pm'} is true, no loading
    happens
16) Test2 finishes compiling
17) Test2 is run (still inside the BEGIN block generated by the "use
    Test2" in TestGlue)
18) "with 'TestRole'" causes a "require TestRole"
19) $INC{'TestRole.pm'} is true, no loading happens
20) the (incomplete!, because we're still compiling it, see point 9)
    role is applied to the Test2 class
21) nothing happens, TestRole is currently an empty role!
22) Test2 finishes running
23) TestGlue finishes compiling
24) TestRole finishes compiling, and only now acquires the sub
    load_role
25) TestRole is finally applied to Test1 (see step 6); Test1 acquires
    the sub load_role
26) Test1 finishes running
27) main loads Test2, but $INC{'Test2.pm'} is true, nothing happens
28) main starts running
29) Test1->new->load works, because 25
30) Test2->new->load fails, because 20 and 21
> 
> Operations Developer
> 1&1 Internet AG
> 


-- 
	Dakkar - <Mobilis in mobile>
	GPG public key fingerprint = A071 E618 DD2C 5901 9574
	                             6FE2 40EA 9883 7519 3F88
	                    key id = 0x75193F88

Warning: Listening to WXRT on April Fools' Day is not recommended for
those who are slightly disoriented the first few hours after waking up.
		-- Chicago Reader 4/22/83

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About