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

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.

Related

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.

Polymorphism in Object construction

I want to create specific Object according to the type argument.
Pseudo code looks like this.
sub new {
my $type = shift;
if($type eq "S1") {$interface = X->new(); }
if($type eq "S2") {$interface = Y->new(); }
etc...
return $interface;
}
Options might be:
Substitute "package" name with $type argument. Requires package name coordination with $type.
Use Hash{S1 => X} in the Master constructor to select Value according to $type passed. Requires Hash maintenance when adding new
Object types.
I don't like any of above. Looking trully polimorphic way to accomplish that.
Thank You,
k
Your best option would likely be to use a factory pattern. A factory method takes the parameters for creating an instance of your class, then decides which object to instantiate and return from that. This can also make dependency injection easier for testing.
You'd probably be looking at something like this (in Java-esque code), with an employee object:
public class EmployeeFactory
{
public static create(String type)
{
switch (type) {
case type1:
return new EmployeeTypeOne();
case type2:
return new EmployeeTypeTwo();
default:
throw new Exception("Unrecognized type");
}
}
}
Your employees would inherit from a common interface or abstract class. You can use the factory to handle constructor parameters as well if you prefer, just try to keep things fairly reasonable (don't pass a million parameters - the factory should internally handle complex objects)
See http://refactoring.com/catalog/replaceConstructorWithFactoryMethod.html for more information.
You might like Module::PluginFinder for that. Create all your specific types in a specific namespace and give them each some identifying (constant? sub?) that the main dispatcher will then use to identify which class handles a given type.

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

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;

Fields in CoffeeScript?

class #A
A_Function_Alias: => #my_function
my_function: =>
usage_of_alias: =>
#A_Function_Alias.call()
What i want, is usage_of_alias to be
usage_of_alias: =>
#A_Function_Alias
And have it behave the same. i.e. I want a more functional style syntax here. I've tried multiple combinations with no success. The fact that i have to evaluate my function to get the goodies inside bothers me.
One application would be instead of this:
event: => new Event(#my_function)
which is accessed as event.call().hi()
i could have some other declaration that would allow me to access event as event.hi()
Something that behaves more like a field instead of a property.
I'm thinking you want this:
class #A
my_function: => alert 'my function!'
A_Function_Alias: #::my_function
usage_of_alias: =>
#A_Function_Alias()
# some other code...
See what this compiles to here.
When evaluating a class # is the class constructor object, the class object itself. And the :: operator lets you drill into the prototype. So #::foo in a class body compiles to MyClass.prototype.foo.
So what this is doing is first making a normal instance method named my_function, defined on A.prototype.my_function. Then we make a new instance method named A_Function_Alias and directly assign the function from class objects prototype that we just created. Now my_function and A_Function_Alias both point to the exact same function object.
But as a more sane alternative, might I suggest a pattern that defines a private inner function that the class can use, and then assigning it more directly, without crazy the prototype accessing?
class #A
# Only code inside this class has access to this local function
innerFunc = -> alert 'my function!'
# Assign the inner funciton to any instance methods we want.
my_function: innerFunc
A_Function_Alias: innerFunc
usage_of_alias: =>
#A_Function_Alias()
# or
#my_function()
# or
innerFunc()
# they all do the same thing

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
...
}