I have this subroutine that gets an object on call from the surrounding system (in this case IRSSI-Proxy):
sub my_method {
my ($obj) = #_;
if( not defined ( $obj->{ someProp } ) ) {
die "someProp is undefined in $obj";
}
}
The function prints out the following message: "someProp is undefined in SomePackage:SomeClass=HASH(0x12345678)".
The so called class "SomePackage:SomeClass" has the property "someProp", but the property inside the passsed instance seems to have no value. But the documentation of the surrounding system says there is one.
I am no Perl developer, but maybe you can point me into a specific direction or maybe provide some debugging techniques?
Sorry guys, after experimenting around a bit and reading other scripts, I found the very easy solution: I was just missing an include directive for the package of the class this object was an instance of. All that was missing was use SomePackage; (or in that case use Irssi::Irc;). After that include, obj->{ someProp } magically had the anticipated value other than undefined.
Thanks everyone for the help, though.
Related
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.
I am rummaging through 7900+ lines of perl code. I needed to change a few things and things were going quite well even though i am just 36 hours into perl. I learned the basic constructs of the language and was able to get small things done. But then suddenly I have found a function call which does not have any definition anywhere. I grep'ed several times to check for all 'sub'. I could not find the functions definition. What am I missing ? Where is the definition of this function. I am quite sure this is a user defined function and not a library function(from its name i guessed this).
Please help me find this function's definition.
Here is a few lines from around the function usage.
(cfg_machine_isActive($ep)) {
staf_var_set($ep, VAR_PHASE, PHASE_PREP);
staf_var_set($ep, VAR_PREP, STATE_RUNNING);
} else {
cfg_machine_set_state($ep, STATE_FAILED);
}
}
$rc = rvt_deploy_library(); #this is the function that is the problem
dump_states() unless ($rc != 0);
Here is the answer:
(i could not post this an answer itself cos i dont have enough reputation)
I found that the fastest way to find the definition of an imported function in perl are the following commands:
>perl.exe -d <filename>.pl
This starts the debugger.
Then; do
b <name of the function/subroutine who's definition you are looking for>
in our case that would mean entering:
b rvt_deploy_library
next press 'c' to jump to the mentioned function/subroutine.
This brings the debugger to the required function. Now, you can see the line no. and location of the function/subroutine on the console.
main::rvt_deploy_library(D:/CAT/rvt/lib/rvt.pm:60):
There are a number of ways to declare a method in Perl. Here is an almost certainly incomplete list:
The standard way, eg. sub NAME { ... }
Using MooseX::Method::Signatures, method NAME (...) {...}
Assignment to a typeglob, eg. *NAME = sub {...};
In addition, if the package declares an AUTOLOAD function, then there may be no explicit definition of the method. See perlsub for more information.
You can inspect any perl value with the B module. In this case:
sub function_to_find {}
sub find_sub (\&) {
my $code = shift;
require B;
my $obj = B::svref_2object($code); # create a B::CV object from $code
print "$code:\n";
print " $$_[0]: $$_[1]\n" for
[file => $obj->FILE],
[line => $obj->GV->LINE],
[name => $obj->GV->NAME],
[package => $obj->STASH->NAME];
}
find_sub &function_to_find;
which prints something like:
CODE(0x80ff50):
file: so.pl
line: 7
name: function_to_find
package: main
B::Xref will show all functions declared in all the files used by your code.
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
...
}
I simply hate how CGI::Application's accessor for the CGI object is called query.
I would like my instance classes to be able to use an accessor named cgi to get the CGI object associated with the current instance of my CGI::Application subclass.
Here is a self-contained example of what I am doing:
package My::Hello;
sub hello {
my $self =shift;
print "Hello #_\n";
}
package My::Merhaba;
use base 'My::Hello';
sub merhaba {
goto sub { shift->hello(#_) };
}
package main;
My::Merhaba->merhaba('StackOverflow');
This is working as I think it should and I cannot see any problems (say, if I wanted to inherit from My::Merhaba: Subclasses need not know anything about merhaba).
Would it have been better/more correct to write
sub merhaba {
my $self = shift;
return $self->hello(#_);
}
What are the advantages/disadvantages of using goto &NAME for the purpose of aliasing a method name? Is there a better way?
Note: If you have an urge to respond with goto is evil don't do it because this use of Perl's goto is different than what you have in mind.
Your approach with goto is the right one, because it will ensure that caller / wantarray and the like keep working properly.
I would setup the new method like this:
sub merhaba {
if (my $method = eval {$_[0]->can('hello')}) {
goto &$method
} else {
# error code here
}
}
Or if you don't want to use inheritance, you can add the new method to the existing package from your calling code:
*My::Hello::merhaba = \&My::Hello::hello;
# or you can use = My::Hello->can('hello');
then you can call:
My::Hello->merhaba('StackOverflow');
and get the desired result.
Either way would work, the inheritance route is more maintainable, but adding the method to the existing package would result in faster method calls.
Edit:
As pointed out in the comments, there are a few cases were the glob assignment will run afoul with inheritance, so if in doubt, use the first method (creating a new method in a sub package).
Michael Carman suggested combining both techniques into a self redefining function:
sub merhaba {
if (my $method = eval { $_[0]->can('hello') }) {
no warnings 'redefine';
*merhaba = $method;
goto &merhaba;
}
die "Can't make 'merhaba' an alias for 'hello'";
}
You can alias the subroutines by manipulating the symbol table:
*My::Merhaba::merhaba = \&My::Hello::hello;
Some examples can be found here.
I'm not sure what the right way is, but Adam Kennedy uses your second method (i.e. without goto) in Method::Alias (click here to go directly to the source code).
This is sort of a combination of Quick-n-Dirty with a modicum of indirection using UNIVERSAL::can.
package My::Merhaba;
use base 'My::Hello';
# ...
*merhaba = __PACKAGE__->can( 'hello' );
And you'll have a sub called "merhaba" in this package that aliases My::Hello::hello. You are simply saying that whatever this package would otherwise do under the name hello it can do under the name merhaba.
However, this is insufficient in the possibility that some code decorator might change the sub that *My::Hello::hello{CODE} points to. In that case, Method::Alias might be the appropriate way to specify a method, as molecules suggests.
However, if it is a rather well-controlled library where you control both the parent and child categories, then the method above is slimmmer.
I'm looking for a general-purpose module to take the drudgery out of validating subroutine and method arguments. I've scanned through various possibilities on CPAN: Params::Validate, Params::Smart, Getargs::Mixed, Getargs::Long, and a few others.
Any information regarding pros and cons of these or other modules would be appreciated. Thanks.
If you start to use Moose, you'll find MooseX::Types to your liking. Types automatically have an is_$type(), and to_$type(). These are for making sure you input passes type constraints, or making your input has a valid coercion to the type. I like them better even for these types of things because you can ensure the state of your object has the said types at no additional cost.
use Moose;
has 'foo' => ( isa => MyType, is => ro );
sub _check_my_type {
my ( $self, $type ) = #_;
is_MyType( $type );
};
It might be lacking some support for deep/recursive types, but if your using this stuff in modern perl you're probably "doing it wrong." Instead use an object that has its own consistency checks (like mine above with MyType), and just pass the object.
Have a look at MooseX::Method::Signatures which provides a bit more than just validating the arguments.
Example from POD:
package Foo;
use Moose;
use MooseX::Method::Signatures;
method morning (Str $name) {
$self->say("Good morning ${name}!");
}
method hello (Str :$who, Int :$age where { $_ > 0 }) {
$self->say("Hello ${who}, I am ${age} years old!");
}
method greet (Str $name, Bool :$excited = 0) {
if ($excited) {
$self->say("GREETINGS ${name}!");
}
else {
$self->say("Hi ${name}!");
}
}
MooseX::Method::Signatures also comes as standard with MooseX::Declare which brings even more sexy syntax to the Perl plate. The above could be written like so (just showing first method for brevity):
use MooseX::Declare;
class Foo {
method morning (Str $name) {
$self->say("Good morning ${name}!");
}
}
There is also a corollary signatures CPAN module for plain subroutines but unfortunately it isn't as feature rich as above.
I am currently researching the same question as the O.P.
I noticed that Dave Rolsky - hyper-productive programmer of Moose fame - has recently (2009) taken over maintenance of Params::Validate, so I think this a good sign. The module has not been upgraded since 2003. So I guess, it still can be used again for checking subroutine params.