How to pass reference to $self->class->method? - perl

I am calling a method as follows:
$self->class->method
I would like to pass a reference to this method as a parameter into a subroutine.
I have tried
\&{ $self->class->method }
but I get the following error:
Unable to create sub named ""
Any ideas on how to do this?

You can take a reference to static class method, but in your case you could use anonymous closure to achieve similar,
my $ref = sub { $self->class->method };
# ..
my $result = $ref->();

The class method is a little strange. I would expect a method with a name like that to return the class string, but it clearly returns an object as it has a method method.
I recommend that you use UNIVERSAL::can, which returns a reference to the given method if it exists. So you can write code like this
my $method_ref = $self->class->can('method');
mysub($method_ref);

You can also use the curry module to achieve this:
use curry;
my $mref = $self->class->curry::method;

Related

perl pass object method reference as parameter to function

i'm trying to do something like this:
-- source file 1
my $queue = Thread::Queue->new();
MyModules::populateQueue(<pass $queue->enqueue method reference);
...
-- package file
package MyModules
sub populateQueue {
my $enqueue = $_[0];
my $item = <find item to add to queue>;
$enqueue->($item);
...
first, i'm not able to add "bless" to Thread::Queue
i've tried a couple of suggestions i found in stackoverflow:
my $enqueueRef = $queue->can('enqueue');
MyModules::populateQueue(\&enqueueRef); <--- fails in the package at line
$enqueue->($item) with undefined subroutine
MyModules::populateQueue(\&queue->enqueue) <-- same failure as above
any idea how to pass a method of an object as a parameter to a function that can then be used in the function?
Perl doesn't have a concept of a bound method reference. my $enqueue = $object->can('method') will return a code ref to a method if it exists, but the code ref isn't bound to that particular object – you still need to pass it as the first argument ($queue->$enqueue($item) or $enqueue->($queue, $item)).
To pass a bound method, the correct solution is to use an anonymous sub that wraps the method call:
populate_queue(sub { $queue->enqueue(#_) });

How to find the Perl code referenced by this line?

I have inherited some Perl code which contains a line that is mysterious to me:
my $binary = A->current->config->settings('arg1', 'arg2')
Basically, I am not sure how to find the related code. "A" is NOT a variable in the local code so I thought this was a class hierarchy. However I checked the directory structure to see if the following path existed, but there was none:
A/current/config/settings.pm
Is A->current->config->settings guaranteed to be a nested class hierarchy, or could it be something else? For example could config actually be a property or method of a different object A->current?
Any assistance you could lend tracking this down would be greatly appreciated!
A is a class name, you should find it in A.pm. current should be a method of the class, defined under a sub current in A.pm. It returns an object whose config method is being called which returns an object again whose settings method is being called with arguments 'arg1' and 'arg2' (well, in fact, the object itself is the first argument).
In fact, any of the methods can return a class instead of an object, too.
Step through the code in the perl debugger and see where it takes you.
foo->bar is a method call, meaning that there is likely a subroutine called bar defined in the package referred to by foo (or a superclass), and gives you no information about whether there is a package bar or foo::bar.
Is A->current->config->settings guaranteed to be a nested class hierarchy
You're thinking of A::current::config::settings.
The following are method calls:
INVOCANT->name
INVOCANT->name(LIST)
That means that A->current->config->settings is a chain of method calls.
The only class named in that code is A.
could config actually be a property or method of a different object A->current?
It's the name of a method of the object or class returned by A->current.
How to find the Perl code referenced by this line?
my $binary = A->current->config->settings('arg1', 'arg2');
is short for
my $obj1 = A->current;
my $obj2 = $obj1->config;
my $binary = $obj2->settings('arg1', 'arg2');
Now that you have the objects available, you can find the class of which they are an instance using
say ref($obj) || "Not a reference";
or
use Scalar::Util qw( blessed );
say blessed($obj) // "Not an object";
As explained, you are dealing with a chain of method calls in the class named A, where at least the first one is a class method since it is invoked on the class (A) itself, not on an object.
An easy way to find that class is by using Class::Inspector
use Class::Inspector;
say "Filename: ", Class::Inspector->resolved_filename( 'A' );
which printed the full path to the class I used in my tests. Also see loaded_filename.
Another interesting way to interrogate a class is to add to it at runtime.
Create an object of A and add to it a method of your choice at runtime
my $objA = A->new();
eval q( sub A::get_info { print "$_\n" for (caller(0)) } );
if ($#) { print "Eval: $#" };
eval q( sub A::boom { croak "Stacktrace: " } );
if ($#) { print "Eval: $#" };
$objA->get_info();
$objA->boom();
These are simple examples but you can acquire practically any information from inside a method.
If A happens to not have a method called new (possible) work with methods in the given chain, starting with my $objA = A->current.
Or, you can directly add a subroutine to the package's symbol table
*{A::new_method} = sub { say "A new method" };
$any_obj_of_A->new_method();
which is now also available on all existing instances, as well as on new ones.

Object class name in perl

I am kinda beginner in perl and I need know how can I check object class name.
My code is:
foreach my $y (keys %$x) {
print "$y\t$x->{$y}\n";
}
with output:
154176568 [object HTMLImageElement]
146292140 [object HTMLDocument]
153907016 [object HTMLImageElement]
I need to print just keys that are HTMLImageElement objects.
Now, question is:
(1) How can I check the class name
(2) How can I get/print class name
In Perl all classes magically extend the UNIVERSAL package. It has a method called isa() that you can use to do this:
foreach my $y (keys %$x) {
if( $x->{$y}->isa('HTMLImageElement') ) {
print "$y\t$x->{$y}\n";
}
}
Looking at the source for JE, it looks like JE::Object::Proxy is a subclass of JE::Object, and JE::Object has a stringification method (use overload fallback => 1, ... '""' => 'to_string' ...).
So when you do print "$y\t$x->{$y}\n";, this is printing the result of stringifying $x->{$y}.
You can stringify the object by putting it in double quotes, so "$x->{$y}". This expression will then have values such as you saw being printed, e.g. '[object HTMLImageElement]'.
If you want to pick up only HTMLImageElement objects, then you could check for these using an expression like
"$x->{$y}" eq '[object HTMLImageElement]'
If you especially want to extract the string 'HTMLImageElement' from the stringified value, you could do that using a regexp, e.g.
("$x->{$y}" =~ m{^\[object (.*)\]$}so)[0]
THOUGH, looking at the source for JE::Object::Proxy, JE::Object::Proxy has a method class which might perhaps return the name of the class that the object is a proxy for. So you might be able to get the class name using $x->{$y}->class, and then be able to test that directly as in $x->{$y}->class eq 'HTMLImageElement'.
If you want a string indicating the class name, use ref($object). This will return the reference type for a variable, which for perl objects, ends up being the package of the blessed object.
If you want to simply check if a variable is an instance of a certain class, use the isa() method. For instance:
if ($obj->isa('Animal::Dog')) {
push #dogs, $obj;
}

How do you introspect MooseX::Method::Signatures methods to see what arguements they take?

I'm using MooseX::Declare and methods, which uses MooseX::Method::Signatures. Let's say I have a class 'foo' with a method 'bar', and I've implemented it like:
class foo {
method bar (Str $str, Bool :$flag = 1) {
# ....
}
}
I now want to write a front-end interface that asks a user what class they want to use, what method on that class they want to use, and then what options to the method they want. I can do the first two things, so let's say the user has now chosen class foo and method bar.
But how do I find out that method bar takes a string as the first argument, and a flag => bool key value pair that defaults to 1? My code needs to know this so I can then ask the user to supply these things.
First, get the method meta object:
my $method = $class->meta->find_method_by_name( $method_name );
Then, make sure it's a signaturey method:
confess "not method with a signature!"
unless $method->isa('MooseX::Method::Signatures::Meta::Method');
Get its signature:
my $sig = $method->parsed_signature;
Then look at $sig's named_params and positional_params as detailed in the Parse::Method::Signatures::Sig docs.
To find parsed_signature, I had to look at the source to MooseX::Method::Signatures::Meta::Method… so be wary when you do this.

How can I check if an object has a specific method?

I want to use a method of an object.
Like $myObject->helloWorld().
However there are a couple of methods so I loop through an array of method names and call the method like this:
my $methodName ="helloWorld";
$myObject->$methodNames;
This works quite nice but some objects don't have all methods.
How can I tell whether $myObject has a method called helloWorld or not?
You can use the UNIVERSAL::can method of all objects to determine what methods it supports:
if ($myObject->can($methodName)) {
$myObject->$methodName;
}
As Eric noted, you can usually use UNIVERSAL::can
It can be used either on an object as in your example ($obj->can($methodName)) or statically, on a class: (CLASS->can($methodName))
Please note that there are possible false negatives associated with using UNIVERSAL::can on objects/classes which have AUTOLOAD-ed methods - see the perldoc for details. So before using can() on an object/class, please be careful to verify that the class in question either does not use AUTOLOAD, or overrides can() to compensate, or uses forward declaration to compensate as described in can()'s perldoc - hat tip to brian d foy)
Also, please be careful to either ONLY call can() on actual objects, or encapsulate it in eval. It will die if called on a non-object (e.g. undef, scalar etc...)
The canonical way to use can is inside an eval block in case the thing that you have in your scalar variable isn't actually an object. You don't have to worry about that because you'll still get the right answer (a non-object or class can't respond to the method):
if( my $ref = eval { $obj->can( $method ) } ) {
$obj->$ref( #args );
}
The can has the added feature that it returns a code reference to the method. Sometimes that can be handy.
I used this method when checking database connections, passed into a function, such as
my $method = "ping";
if(defined ($local_dbh) && eval{ $local_dbh->can($method) } ) {
if ($local_dbh->ping) {
return $local_dbh;
}
}
else {
## do connection
...
}