How to handle: Moo :: The `before` modifier motif is silently skipped due to circular import?

Using Moo::Role, I find that cyclic import silently prevents the execution of the modifier of beforemy method.

I have Moo::Rolein MyRole.pm:

package MyRole;
use Moo::Role;
use MyB;
requires 'the_method';
before the_method => sub { die 'This has been correctly executed'; };
1;

... consumer in MyA.pm:

package MyA;
use Moo;
with ( 'MyRole' );
sub the_method { die; }
1;

.. and another in MyB.pm:

package MyB;
use Moo;
with ( 'MyRole' );
sub the_method { die 'The code should have died before this point'; }
1;

When I run this one script.pl:

#!/usr/bin/env perl
package main;
use MyA;
use MyB;
MyB->new()->the_method();

... I receive The code should have died before this point at MyB.pm line 4., but expect to see This has been correctly executed at MyRole.pm line 5.

I think this problem is caused by circular imports. It disappears when I switched the order of the operators usein script.plor changing use MyB;in MyRole.pmhow requireinside the_method.

Is this behavior expected? If so, what is the best way to handle this when cyclic imports cannot be avoided?

, ( , before, , ).

( Moo 2.003004. , use MyB; in MyRole.pm , , .)

+6
1

, . :

  • use Some::Module BEGIN { require Some::Module; Some::Module->import }
  • , . BEGIN .
  • require 'd . , require .

, , require d BEGIN.

:

use MyA;
use MyB;
MyB->new()->the_method();

use BEGIN { require ... } MyA. ->import MyA MyB, .

BEGIN { # use MyA;
  package MyA;
  use Moo;
  with ( 'MyRole' );
  sub the_method { die; }
}
BEGIN { # use MyB;
  require MyB;
}
MyB->new()->the_method();

with('MyRole') a require MyRole, :

  ...
  require MyRole;
  with( 'MyRole ');

, :

BEGIN { # use MyA;
  package MyA;
  use Moo;
  { # require MyRole;
    package MyRole;
    use Moo::Role;
    use MyB;
    requires 'the_method';
    before the_method => sub { die 'This has been correctly executed'; };
  }
  with ( 'MyRole' );
  sub the_method { die; }
}
BEGIN { # use MyB;
  require MyB;
}
MyB->new()->the_method();

use MyB, MyB with('MyRole') a require:

BEGIN { # use MyA;
  package MyA;
  use Moo;
  { # require MyRole;
    package MyRole;
    use Moo::Role;
    BEGIN { # use MyB;
      package MyB;
      use Moo;
      require MyRole;
      with ( 'MyRole' );
      sub the_method { die 'The code should have died before this point'; }
    }
    requires 'the_method';
    before the_method => sub { die 'This has been correctly executed'; };
  }
  with ( 'MyRole' );
  sub the_method { die; }
}
BEGIN { # use MyB;
  require MyB;
}
MyB->new()->the_method();

MyB require MyRole, . . MyRole :

package MyRole;
use Moo::Role;

, . requires 'the_method'; before the_method => sub { ... } .

MyB , the_method.


? use , , . .

use , (, ), . , , . , require , . a require , , state $require_once = require Some::Module. , .

: , . . , : , .

, . ? , , , . ( A: ).

, . , , .

+3

All Articles