How to find the Perl code referenced by this line? - perl

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.

Related

multi-level inheritance in Perl

I have a question related to multi-level inheritance in Perl.
Here is my code
mod.pm
package first;
sub disp {
print "INSIDE FIRST\n";
}
package second;
#ISA = qw(first);
sub disp {
print "INSIDE SECOND\n";
}
package third;
#ISA = qw(second);
sub new {
$class = shift;
$ref = {};
bless $ref, $class;
return $ref;
}
sub show {
$self = shift;
print "INSIDE THIRD\n";
}
1;
prog.pl
use mod;
$obj = third->new();
$obj->show();
$obj->disp();
I have a .pm file which contains three classes. I want to access the disp method in the first class using an object of third class. I'm not sure how that could work.
I tried to access using two ways:
using class name => first::disp()
using SUPER inside second package disp method => $self->SUPER::disp();
But am not sure how it will be accessed directly using the object of third class.
$obj->first::disp(), but what you are asking to do is something you absolutely shouldn't do. Fix your design.
If you need to do that, then you have defined your classes wrongly.
The third class inherits from the second class. second has it's own definition of disp, so it never tries to inherit that method from its superclass first. That means third gets the implementation defined in second
The simple answer would be to call first::disp something else. That way second won't have a definition of the method and inheritance will be invoked again
If you explain the underlying problem, and why you want to ignore an inherited method, then perhaps we can help you find a better way
Please also note that packages and module files should start with a capital letter, and each class is ordinarily in a file of its own, so you would usually use package First in First.pm etc.

Undefined reference when accessing a object hash

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.

perl constructor keyword 'new'

I am new to Perl and currently learning Perl object oriented and came across writing a constructor.
It looks like when using new for the name of the subroutine the first parameter will be the package name.
Must the constructor be using the keyword new? Or is it because when we are calling the new subroutine using the packagename, then the first parameter to be passed in will be package name?
packagename->new;
and when the subroutine have other name it will be the first parameter will be the reference to an object? Or is it because when the subroutine is call via the reference to the object so that the first parameter to be passed in will be the reference to the object?
$objRef->subroutine;
NB: All examples below are simplified for instructional purposes.
On Methods
Yes, you are correct. The first argument to your new function, if invoked as a method, will be the thing you invoked it against.
There are two “flavors” of invoking a method, but the result is the same either way. One flavor relies upon an operator, the binary -> operator. The other flavor relies on ordering of arguments, the way bitransitive verbs work in English. Most people use the dative/bitransitive style only with built-ins — and perhaps with constructors, but seldom anything else.
Under most (but not quite all) circumstances, these first two are equivalent:
1. Dative Invocation of Methods
This is the positional one, the one that uses word-order to determine what’s going on.
use Some::Package;
my $obj1 = new Some::Package NAME => "fred";
Notice we use no method arrow there: there is no -> as written. This is what Perl itself uses with many of its own functions, like
printf STDERR "%-20s: %5d\n", $name, $number;
Which just about everyone prefers to the equivalent:
STDERR->printf("%-20s: %5d\n", $name, $number);
However, these days that sort of dative invocation is used almost exclusively for built-ins, because people keep getting things confused.
2. Arrow Invocation of Methods
The arrow invocation is for the most part clearer and cleaner, and less likely to get you tangled up in the weeds of Perl parsing oddities. Note I said less likely; I did not say that it was free of all infelicities. But let’s just pretend so for the purposes of this answer.
use Some::Package;
my $obj2 = Some::Package->new(NAME => "fred");
At run time, barring any fancy oddities or inheritance matters, the actual function call would be
Some::Package::new("Some::Package", "NAME", "fred");
For example, if you were in the Perl debugger and did a stack dump, it would have something like the previous line in its call chain.
Since invoking a method always prefixes the parameter list with invocant, all functions that will be invoked as methods must account for that “extra” first argument. This is very easily done:
package Some::Package;
sub new {
my($classname, #arguments) = #_;
my $obj = { #arguments };
bless $obj, $classname;
return $obj;
}
This is just an extremely simplified example of the new most frequent ways to call constructors, and what happens on the inside. In actual production code, the constructor would be much more careful.
Methods and Indirection
Sometimes you don’t know the class name or the method name at compile time, so you need to use a variable to hold one or the other, or both. Indirection in programming is something different from indirect objects in natural language. Indirection just means you have a variable that contains something else, so you use the variable to get at its contents.
print 3.14; # print a number directly
$var = 3.14; # or indirectly
print $var;
We can use variables to hold other things involved in method invocation that merely the method’s arguments.
3. Arrow Invocation with Indirected Method Name:
If you don’t know the method name, then you can put its name in a variable. Only try this with arrow invocation, not with dative invocation.
use Some::Package;
my $action = (rand(2) < 1) ? "new" : "old";
my $obj = Some::Package->$action(NAME => "fido");
Here the method name itself is unknown until run-time.
4. Arrow Invocation with Indirected Class Name:
Here we use a variable to contain the name of the class we want to use.
my $class = (rand(2) < 1)
? "Fancy::Class"
: "Simple::Class";
my $obj3 = $class->new(NAME => "fred");
Now we randomly pick one class or another.
You can actually use dative invocation this way, too:
my $obj3 = new $class NAME => "fred";
But that isn’t usually done with user methods. It does sometimes happen with built-ins, though.
my $fh = ($error_count == 0) ? *STDOUT : *STDERR;
printf $fh "Error count: %d.\n", $error_count;
That’s because trying to use an expression in the dative slot isn’t going to work in general without a block around it; it can otherwise only be a simple scalar variable, not even a single element from an array or hash.
printf { ($error_count == 0) ? *STDOUT : *STDERR } "Error count: %d.\n", $error_count;
Or more simply:
print { $fh{$filename} } "Some data.\n";
Which is pretty darned ugly.
Let the invoker beware
Note that this doesn’t work perfectly. A literal in the dative object slot works differently than a variable does there. For example, with literal filehandles:
print STDERR;
means
print STDERR $_;
but if you use indirect filehandles, like this:
print $fh;
That actually means
print STDOUT $fh;
which is unlikely to mean what you wanted, which was probably this:
print $fh $_;
aka
$fh->print($_);
Advanced Usage: Dual-Nature Methods
The thing about the method invocation arrow -> is that it is agnostic about whether its left-hand operand is a string representing a class name or a blessed reference representing an object instance.
Of course, nothing formally requires that $class contain a package name. It may be either, and if so, it is up to the method itself to do the right thing.
use Some::Class;
my $class = "Some::Class";
my $obj = $class->new(NAME => "Orlando");
my $invocant = (rand(2) < 1) ? $class : $obj;
$invocant->any_debug(1);
That requires a pretty fancy any_debug method, one that does something different depending on whether its invocant was blessed or not:
package Some::Class;
use Scalar::Util qw(blessed);
sub new {
my($classname, #arguments) = #_;
my $obj = { #arguments };
bless $obj, $classname;
return $obj;
}
sub any_debug {
my($invocant, $value) = #_;
if (blessed($invocant)) {
$invocant->obj_debug($value);
} else {
$invocant->class_debug($value);
}
}
sub obj_debug {
my($self, $value) = #_;
$self->{DEBUG} = $value;
}
my $Global_Debug;
sub class_debug {
my($classname, $value) = #_;
$Global_Debug = $value;
}
However, this is a rather advanced and subtle technique, one applicable in only a few uncommon situations. It is not recommended for most situations, as it can be confusing if not handled properly — and perhaps even if it is.
It is not first parameter to new, but indirect object syntax,
perl -MO=Deparse -e 'my $o = new X 1, 2'
which gets parsed as
my $o = 'X'->new(1, 2);
From perldoc,
Perl suports another method invocation syntax called "indirect object" notation. This syntax is called "indirect" because the method comes before the object it is being invoked on.
That being said, new is not some kind of reserved word for constructor invocation, but name of method/constructor itself, which in perl is not enforced (ie. DBI has connect constructor)

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

In Perl, what is the right way for a subclass to alias a method in the base class?

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.