in reply to find all modules that "do" a role

I haven't done anything with Moose, but I suppose that using Module::Pluggable to find all candidates and then using some part of the Moose API to inspect $package->metaclass is the approach I'd use. Actually, looking at Moose::Meta::Class, the following should tell you whether a class does a role:

package App; use Module::Pluggable sub_name => 'plugins'; my @candidates = App->plugins; for my $class (@candidates) { if ($class->meta->does_role( $role ) { print "$class does $role\n"; }; };

Of course, with this unchecked approach, you force all plugins into the Moose tarpit, which imposes a burden+learning curve on plugin authors. You might want to be more defensive, by wrapping $class->meta in an eval block or by providing a base class for plugins which sets up enough routines for a bare-bones plugin that does no harm.

Update: Upon rereading, I see that you only want to look at the classes that have been loaded - then, I'd stay with the defensive approach outlined above, but fill the @candidates from %INC instead via Module::Pluggable, if you want to avoid setting up Module::Pluggable with the correct search paths or want to avoid (re)loading failing modules.

Replies are listed 'Best First'.
Re^2: find all modules that "do" a role
by Anonymous Monk on Sep 07, 2009 at 15:26 UTC

    You're right, Module::Pluggable would give me a good set to start checking. The thing is that I didn't want to depend on M::P, but also check things that were used or required.

    I suppose that, wheather using %INC, or ${*::*}, I'll need to check if the class uses "moose" before invoking $class->meta.

      Module::Pluggable is core, so the only burden would be (again) upon the plugin author. Personally, I wouldn't check whether a class/package uses Moose but rather just do

      my $metaclass = eval { $class->meta }; if ($metaclass) { };

      that way non-Moose things have an option to work as plugins as well, as long as they have:

      sub meta { ... }

      which returns something "good enough". For example the following should work for your use case as a minimal class:

      package My::Plugin; sub meta { __PACKAGE }; sub does_role { my ($class,$role) = @_; $role eq 'chatbot' }; 1