How do I list available methods on a given object or package in Perl? - perl

How do I list available methods on a given object or package in Perl?

There are (rather too) many ways to do this in Perl because there are so many ways to do things in Perl. As someone commented, autoloaded methods will always be a bit tricky. However, rather than rolling your own approach I would suggest that you take a look at Class::Inspector on CPAN. That will let you do something like:
my $methods = Class::Inspector->methods( 'Foo::Class', 'full', 'public' );

If you have a package called Foo, this should do it:
no strict 'refs';
for(keys %Foo::) { # All the symbols in Foo's symbol table
print "$_\n" if exists &{"Foo::$_"}; # check if symbol is method
}
use strict 'refs';
Alternatively, to get a list of all methods in package Foo:
no strict 'refs';
my #methods = grep { defined &{"Foo::$_"} } keys %Foo::;
use strict 'refs';

if you have a package that is using Moose its reasonably simple:
print PackageNameHere->meta->dump;
And for more complete data:
use Data::Dumper;
print Dumper( PackageNameHere->meta );
Will get you started. For everything else, theres the methods that appear on ->meta that are documented in Class::MOP::Class
You can do a bit of AdHoc faking of moose goodness for packages without it with:
use Class::MOP::Class;
my $meta = Class::MOP::Class->initialize( PackageNameHere );
and then proceed to use the Class::MOP methods like you would with Moose.
For starters:
$meta->get_method_map();
use Moose; #, its awesome.

In general, you can't do this with a dynamic language like Perl. The package might define some methods that you can find, but it can also make up methods on the fly that don't have definitions until you use them. Additionally, even calling a method (that works) might not define it. That's the sort of things that make dynamic languages nice. :)
What task are you trying to solve?

A good answer from How to get structure and inheritance history
The classes from which an object's class currently inherits can be found using the following:
use mro qw( );
use Scalar::Util qw( blessed );
say join ", ", #{ mro::get_linear_isa(blessed($o)) };

Related

How to create globally available functions in Perl?

Is it possible to create global functions available across all namespaces like perl built-in functions?
First of all, "function" is the name given to Perl's named list operators, named unary operators and named nullary operators. They are visible everywhere because they are operators, just like ,, && and +. Subs aren't operators.
Second of all, you ask how to create a global sub, but all subs are already global (visible from everywhere) in Perl! You simply need to quality the name of the sub with the package if it's not in the current package. For example, Foo::mysub() will call my_sub found in package Foo from anywhere.
But maybe you want to be able to say mysub() instead of Foo::mysub() from everywhere, and that's a very bad idea. It violates core principles of good programming. The number of types of problems it can cause are too numerous to list.
There is a middle ground. A better solution is to create a sub that can be imported into the namespaces you want. For example, say you had the module
package Foo;
use Exporter qw( import );
our #EXPORT_OK = qw( my_sub );
our %TAGS = ( ALL => \#EXPORT_OK );
sub my_sub { ... }
1;
Then, you can use
use Foo qw( my_sub );
to load the module (if it hasn't already been loaded) and create my_sub in the current package. This allows it to call the sub as my_sub() from the package into which it was imported.
There is nothing simple that would allow one to somehow "register" user's subs with the interpreter, or some such, so that you could run them as builtins in any part of the program.
One way to get the behavior you ask for is to directly write to symbol tables of loaded modules. This has to be done after the modules have been loaded, and after subs that you add to those modules have been defined. I use INIT block in the example below.
Note that this has a number of weaknesses and just in general the idea itself is suspect to me, akin to extending the interpreter. Altogether I'd much rather write a module with all such subs and use standard approaches for good program design to have that module loaded where it needs to go.
Having said that, here is a basic demo
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd pp);
use TestMod qw(modsub);
sub t_main { say "In t_main(), from ", __PACKAGE__ }
modsub("Calling from main::");
INIT {
no strict 'refs';
foreach my $pkg (qw(TestMod)) {
*{ $pkg . '::' . 'sub_from_main' } = \&t_main;
}
dd \%TestMod::;
}
This copies the reference to t_main from the current package (main::) into the symbol table of $pkg, under the name of sub_from_main, which can then be used with that name in that package.
For simplicity the name of the module is hardcoded, but you can use %INC instead, and whatever other clues you have, to figure out what loaded modules' stashes to add to.
The benefactor (or the victim?) module TestMod.pm
package TestMod;
use warnings;
use strict;
use feature 'say';
use Exporter qw(import);
our #EXPORT_OK = qw(modsub);
sub modsub {
say "In module ", __PACKAGE__, ", args: #_";
say "Call a sub pushed into this namespace: ";
sub_from_main();
}
1;
The name of the added sub can be passed to modules as they're loaded, instead of being hardcoded, in which case you need to write their import sub instead of borrowing the Exporter's one.
There are also modules that allow one to add keywords, but that's no light alternative.
The answer seems to be no, but you can impliment most of the behaivior that you want by using the symbol table *main::main:: to define a subroutine in all the namespaces.
use strict;
use warnings;
use Data::Dump qw(dd);
my $xx = *main::main::;
package A;
sub test {
printf "A::%s\n", &the_global;
}
package B;
sub the_global
{
"This is B::the_global";
}
sub test {
printf "B::%s\n", &the_global;
}
package main;
my $global_sub = sub { "The Global thing" };
for my $NS (keys %$xx) {
if ($NS =~ /^[A-Z]::$/) {
my $x = $NS . 'the_global';
if (defined &$x) {
printf "Skipping &%s\n", $x;
} else {
printf "Adding &%s\n", $x;
no strict 'refs';
*$x = $global_sub;
}
}
}
A::test;
This will not work on packages that are not referenced at all before the for loop above is run. But this would only happen if a require, use or package was eval'd after the code started running.
This is also still a compiler issue! You either need to refer to the global function as the_global() or &the_global if you are (as you should be) using use strict.
Sorry for my late response and thank you all for yours detailed answers and explanations.
Well.. I understood the right answer is: IT'S NOT POSSIBLE!
I'm mantaining a Perl framework used by some customers, and that framework exports some specialized subs (logging, event handling, controllers for hardware devices, domain specific subs and so). That's why I tried to figure out how to prevent the developers from importing my subs in all their packages.

What is the best practice for finding all the superclasses of a Perl class?

Is there a standard CPAN way of finding out all the superclasses of a Perl class (or better yet entire superclass tree, up to UNIVERSAL)?
Or is the best practice to simply examine #{"${$class}::ISA"} for each class, class's parents etc?
There is no "standard way" because this is not a standard thing you want to do. For anything other than visualization it is an OO red flag to want to inspect your inheritance tree.
In addition to Class::ISA, there is mro::get_linear_isa(). Both have been in core for a while so they could be considered "standard" for some definition. Both of those show inheritance as a flat list, not a tree, which is useful mostly for deep magic.
The perl5i meta object provides both linear_isa(), like mro (it just calls mro), and ISA() which returns the class' #ISA. It can be used to construct a tree using simple recursion without getting into symbol tables.
use perl5i::2;
func print_isa_tree($class, $depth) {
$depth ||= 0;
my $indent = " " x $depth;
say $indent, $class;
for my $super_class ($class->mc->ISA) {
print_isa_tree($super_class, $depth+1);
}
return;
}
my $Class = shift;
$Class->require;
print_isa_tree($Class);
__END__
DBIx::Class
DBIx::Class::Componentised
Class::C3::Componentised
DBIx::Class::AccessorGroup
Class::Accessor::Grouped
I think Class::ISA is something like you are looking for
use Class::ISA;
use Mojolicious;
print join "\n", Class::ISA::super_path("Mojolicious");
Prints:
Mojo
Mojo::Base
However, it's not some kind of "best practice" since the whole task isn't something Perl programmers do every day.
Most likely these days you want to use one of the functions from mro, such as mro::get_linear_isa.
use mro;
my #superclasses = mro::get_linear_isa($class);
I don't believe that there is something like a "standard CPAN way". Examining #ISA is common practice - and also plausible, since techniques like use base qw(...) and use parent -norequire, ... also operate on top of #ISA...

Do Perl subclasses inherit imported modules and pragmas?

Lets say you have a parent Perl class in one file:
#!/usr/bin/perl
package Foo;
use strict;
use warnings;
use Data::Dumper;
sub new{
my $class = shift;
my %self = ();
return bless %self, $class;
}
1;
and a subclass in a different file:
#!/usr/bin/perl
package Bar;
use base "Foo";
1;
Will the subclass inherit the use statements from the parent? I know the method new will be inherited.
Basically I am trying to reduce the amount of boilerplate in my code and I can't find a clear answer to this question.
You asked in a comment about Test::Most and how it reduces boilerplate. Look at its import method. It's loading the modules into its namespace, adding those symbols to #EXPORT, then re-calling another import through a goto to finally get them into the calling namespace. It's some serious black magic that Curtis has going on there, although I wonder why he just didn't use something like import_to_level. Maybe there are some side effects I'm not thinking about.
I talk quite a bit about this sort of thing in Avoid accidently creating methods from module exports in The Effective Perler. It's in a different context but it's some of the same issues.
Here's a different example.
If some other module loads a module, you have access to it. It's not good to depend on that though. Here are three separate files:
Top.pm
use 5.010;
package Top;
use File::Spec;
sub announce { say "Hello from top!" }
1;
Bottom.pm
package Bottom;
use parent qw(Top);
sub catfiles { File::Spec->catfile( #_ ) }
1;
test.pl
use 5.010;
use Bottom;
say Bottom->catfiles( qw(foo bar baz) );
say File::Spec->catfile( qw( one two three ) );
I only load File::Spec in Top.pm. However, once loaded, I can use it anywhere in my Perl program. The output shows that I was able to "use" the module in other files even though I only loaded it in one:
Bottom/foo/bar/baz
one/two/three
For this to work, the part of the code that loads the module has to load before any other part of the code tries to use that module. As I said, it's a bad idea to depend on this: things break if the loading sequence changes or the loading module disappears.
If you want to import symbols, however, you have to explicitly load the module you want while you are in the package you want to import into. That's just so the exporting module defines the symbols in that package. It's not something that depends with scope.
Ah, good question!
Will the subclass inherit the use statements from the parent?
Well this depends on what you mean by inherit. I won't make any assumptions until the end, but the answer is maybe. You see, perl mixes the ideas of Classes, and Namespaces -- a package is a term that can describe either of them. Now the issue is the statement use all it does is force a package inclusion, and call the targets import() sub. This means it essentially has unlimited control over your package - and by way of that your class.
Now, compound this with all methods in perl being nothing more than subs that take $self as a first argument by convention and you're left with perl5. This has an enormous upside for those that know how to use it. While strict is a lexical pragma, what about Moose?
package BigMooseUser;
use Moose;
package BabyMooseUser;
our #ISA = 'BigMooseUser';
package Foo;
my $b = BabyMooseUser->new;
print $b->meta->name;
Now, where did BabyMooseUser get the constructor (new) from? Where did it get the meta class from? All of this is provided from a single use Moose; in the parent class (namespace). So
Will the subclass inherit the use statements from the parent?
Well, here, in our example, if the effects of the use statement are to add methods, than certainly.
This subject is kind of deep, and it depends if you're talking about pragmas, or more obscure object frameworks, or procedural modules. If you want to mitigate a parents namespace from affecting your own in the OO paradigm see namespace::autoclean.
For boilerplate reduction, I have a couple of strategies: Most of my classes are Moose classes, which takes care of OO setup and also gives me strict and warnings. If I want to have functions available in many packages, I'll create a project specific MyProject::Util module that uses Sub-Exporter to provide me with my own functions and my own interface. This makes it more consistent, and if I decide to change the Dumper (for example) later for whatever reason, I don't have to change lots of code. That'll also allow you to group exports. A class then usually looks something like this:
package Foo;
use Moose;
use MyProject::Util qw( :parsing :logging );
use namespace::autoclean;
# class implementation goes here
1;
If there's other things you regard as boilerplate and want to make simpler to include, it of course depends on what those things are.
A pragmatic answer to your problem: Either use, or look at how Modern::Perl does it to enforce strict and warnings.
You can get a definitive answer by examining the symbol tables for each package:
# examine-symbol-tables.pl
use Bar;
%parent_names = map{$_ => 1} keys %Foo::;
%child_names = map{$_ => 1} keys %Bar::;
delete $parent_names{$_} && ($common_names{$_} = delete $child_names{$_}) foreach keys %child_names;
print "Common names in symbol tables:\n";
print "#{[keys %common_names]}\n\n";
print "Unique names in Bar symbol table:\n";
print "#{[keys %child_names]}\n\n";
print "Unique names in Foo symbol table:\n";
print "#{[keys %parent_names]}\n\n";
$ perl inherit.pl
Common names in symbol tables:
BEGIN
Unique names in Bar symbol table:
ISA isa import
Unique names in Foo symbol table:
Dumper new VERSION

Is using __PACKAGE__ inside my methods bad for inheritance?

If inside my code I'll have calls like:
__PACKAGE__->method;
will this limit the usability of this module, if this module is inherited?
It depends on what you want to do:
#!/usr/bin/perl
package A;
use strict; use warnings;
sub new { bless {} => $_[0] }
sub method1 {
printf "Hello from: %s\n", __PACKAGE__;
}
sub method2 {
my $self = shift;
printf "Hello from: %s\n", ref($self);
}
package B;
use strict; use warnings;
use parent 'A';
package main;
my $b = B->new;
$b->method1;
$b->method2;
Output:
Hello from: A
Hello from: B
If you intend to inherit that method, call it on the referent and don't rely on the package you find it in. If you intend to call a method internal to the package that no other package should be able to see, then it might be okay. There's a fuller explanation in Intermediate Perl, and probably in perlboot (which is an extract of the book).
In general, I try not to ever use __PACKAGE__ unless I'm writing a modulino.
Why are you trying to use __PACKAGE__?
That depends. Sometimes __PACKAGE__->method() is exactly what you need.
Otherwise it's better to use ref($self)->class_method() or $self->method().
"It depends." is the correct answer. It is relatively uncommon to actually need the package name; usually you will have an instance or a class name to start with. That said, there are times when you really do need the package name -- __PACKAGE__ is clearly the tool for that job, being superior to a literal. Here are some guidelines:
Never call methods off __PACKAGE__ inside methods, as doing so makes it impossible for inheritors to change your implementation by simply overriding the called method. Use $self or $class instead.
Try to avoid __PACKAGE__ inside methods in general. Every use of __PACKAGE__ adds a little bit of inflexibility. Sometimes, inflexibility is what you want (because you need compile-time resolution or badly want to control where information is being stored), but be triply sure that what you want is worth the cost. You'll thank yourself later.
Outside of methods, you don't have access to a $self, and should call methods off __PACKAGE__ rather than a literal. This is mostly important for compile-time declarations like those provided by Class::Accessor.

How can I extend Moose's automatic pragma exports?

You know how Moose automatically turns on strict and warnings during import? I want to extend that behavior by turning on autodie and use feature ':5.10' in my Moose classes.
I've tracked down where Moose does this, in Moose::Exporter, which assembles a custom import sub for Moose that calls strict->import and warnings->import for the calling class.
However, I can't figure out a way to extend this import method in a Moose-ish way.
How should I handle this?
http://www.friedo.com/bullwinkle.gif
My approach solves the problem backwards.
Why not use ToolSet to create a group of use statements that includes Moose, along with your additional pragmas?
The code should look something like:
# MagicMoose.pm
package MagicMoose;
use base 'ToolSet';
ToolSet->use_pragma( qw/feature :5.10/ ); # perl 5.10
ToolSet->use_pragma( qw/autodie/ );
# define exports from other modules
ToolSet->export(
'Moose' => undef, # get the defaults
);
1; # modules must return true
I haven't tested this. Frankly, I just found ToolSet a few days ago, and haven't had a chance to try it out yet. FWIW, the reviews are positive.
Since there are many ways a module might export its functions into the use-ing namespace, you may need to do some code digging in order to implement each desired library. What you're asking for isn't anything specific to Moose, so you can write your or your company's own best practices module which will set up a group of standards for you to work with, e.g.
use OurCompany::BestPractices::V1;
with
package OurCompany::BestPractices::V1;
use strict;
use warnings;
use feature (':5.10');
require Fatal;
require Moose;
# Required for straight implementation of autodie code
our #ISA;
push #ISA, qw(
Fatal
);
sub import {
my $caller = caller;
strict->import;
warnings->import;
feature->import( ':5.10' );
Moose->import ({into => $caller});
#autodie implementation copied from autodie source
splice(#_,1,0,Fatal::LEXICAL_TAG);
goto &Fatal::import;
}
1;
Autodie makes things a little more complicated since it relies on finding the use-er's package from caller() and uses the goto, but you may be able to find a better way with more testing. The more you implement, the more complicated this library might be, but it might be of high enough value for you to have the one-off solution that you can use within all you or your company's code.
Moose::Exporter will allow you to define a custom import method for a sugar class you're using. MooseX::POE used a version of this for years, but does so in what I consider a "hackish" fashion. Looking at the documentation for Moose::Exporter the following should be roughly what you're asking for
package Modern::Moose;
use Moose ();
use Moose::Exporter;
my ($import) = Moose::Exporter->build_import_methods(
also => 'Moose',
install => [qw(unimport init_meta)],
);
sub import { # borrowing from mortiz's answer for feature/mro
feature->import( ':5.10' );
mro::set_mro( scalar caller(), 'c3' );
goto &$import;
}
This can then be used like so
package MyApp;
use Modern::Moose;
has greeting => (is => 'ro', default => 'Hello');
sub run { say $_[0]->greeting } # 5.10 is enabled
You have to define a sub called import in your package, and import all the other stuff there.
An example from Modern::Perl (another policy module you might look at):
use 5.010_000;
use strict;
use warnings;
use mro ();
use feature ();
sub import {
warnings->import();
strict->import();
feature->import( ':5.10' );
mro::set_mro( scalar caller(), 'c3' );
}
Update: Sorry, didn't read the question carefully enough.
A good way to extend an existing import method is to write your own in a new package, and call Moose's import method from there. You can do that by subclassing, maybe you can even use Moose yourself for that ;-)