How can I tell if an object has a specific overloaded method? - perl

I want to check if an object has a specific overload method in perl - for example if it has a sub dereferencing overload that would have been defined like this:
use overload
'&{}' => \&_some_sub;
sub some_sub {...}
If I dump the symbol table of the package that created the object in question I see the following:
[
"new",
"import",
"((",
"(&{}",
"ISA",
"__ANON__",
"BEGIN",
]
Does finding (&{} in the symbol table always mean that a sub deref methd exists? and does it work for other overloads too (I see ("" if I overload stringification).

The details of how overload works under the hood isn't documented very well, and the first line of the IMPLEMENTATION section is What follows is subject to change RSN. So you can't depend on checking the symbol table.
The module does, however, provide a way to see if an operator is overloaded for an object:
overload::Method(obj,op)
Returns undef or a reference to the method that implements op.
So you can use
if (overload::Method($someobj, '&{}')) {
# Overloaded sub deref
}

Related

How do I get to these blessed variables?

I'm trying to use an obscurely documented library that seems to be returning something blessed
bless has never made sense even after reading a number of attempts at explaining it, so I'll just ask the simple question of how do I get to these member variables?
The error message seems to conflict with the Data::Dumper output, though on the off chance that $vm_ds needed to be blessed, I tried adding "bless($vm_ds, 'ManagedObjectReference');" in and just got
Not a HASH reference at blib/lib/Class/MethodMaker/scalar.pm (autosplit into blib/lib/auto/Class/MethodMaker/scalar/scal0000.al) line 252.
for my trouble.
my $vm_ds = $vm_view->datastore;
print "--datastore--\n";
print Dumper($vm_ds);
print "vm_ds1: ", $vm_ds->value, "\n";
exit 0;
$VAR1 = [
bless( {
'value' => 'filer01-cvo-2.fs.peak.org:/vol/vmfs01',
'type' => 'Datastore'
}, 'ManagedObjectReference' )
];
Can't call method "value" on unblessed reference at ./getvms line 93.
$vm_ds is a reference to an array of one blessed hash, so it is $vm_ds->[0] that is blessed into ManagedObjectReference. You can extract the value field using $vm_ds->[0]{value}, but it is very wrong to access object atributes directly like this, and is equivalent to accessing a private attribute
bless is Perl's object-oriented mechanism, and the class that a data item is blessed into specifies which Perl package contains the methods and data for the class
Somewhere you have a .pm file with package ManagedObjectReference and a number of subroutines which are the methods for the class. These supply the official interface to the class, and if you're lucky then there is a value method which is the accessor method for the value attribute. Try calling $vm_ds->[0]->value() and see if that works, otherwise you need to read the documentation for your ManagedObjectReference class
$vm_ds is a reference to an array (hence the [ ... ] in Dumper output) with one item being an instance of class ManagedObjectReference (this is the meaning of bless: saying that something is an instance of some class)
So you need to do $vm_ds->[0]->value() instead of $vm_ds->value(). 0 will be the first item in the array (your example shows only one item, but in a generic case your array reference may contain multiple items).

PERL: ref, shift keyword [duplicate]

This question already has answers here:
What does shift() do in Perl?
(7 answers)
Closed 6 years ago.
I am going through the following subroutine:
sub new{
my $self = shift;
my $class = ref($self) || $self;
}
Here, I don't understand what does shift is used for? What I understand from googling is that, shift returns and deletes the leftmost value of the array. But still I am not sure.
Another question, what does ref is used for? Google says it acts as typeof function that returns the type like scalar, array, hashes.
Still I am not sure about my understanding. Can someone please clarify?
When you call a subroutine in Perl any arguments you supply will be available to the subroutine in a special array called #_.
The shift function takes an array as an argument, removes the first element from the array and returns that value.
However, if you call shift without passing it an array, it operates on the #_ array.
So for example if you call a subroutine like this:
my_sub('one', 'two', 'three');
And the definition of my_sub starts like this:
sub my_sub {
my $arg1 = shift;
Then the $arg1 variable will contain the string 'one' and the #_ array will be left with ('two', 'three').
The code you're trying to understand seems to relate to object oriented coding. If you call a method on an object like this:
$obj->my_method('one');
Then the my_method subroutine will actually be passed two arguments in #_. The first is the object that the method was invoked on (sometimes called the invocant) which in this example is $obj. The second argument will be the string 'one'.
It is very common in object-oriented code to start a method definition like this:
sub my_method {
my $self = shift;
Which means $self will now contain the invocant and #_ will be left with all the remaining arguments.
In your specific example, you were looking at a constructor which is a special kind of method. Usually it would be called like this:
my $my_obj = MyClass->new($arg1, $arg2);
In which case the invocant will be the name of the class that the new method was invoked on - the string 'MyClass' in this example.
It would also be possible to invoke the constructor function on an existing object like this:
my $new_obj = $my_obj->new($arg1, $arg2);
Exactly what the result of this call should be is not at all clear to the casual reader. Should it be a completely new object that is a clone of $my_obj or should it be a new object that has nothing in common with $my_obj at all? In the first case, defining a clone method would be clearer and in the second case, calling the constructor on the class would be clearer.
Your example code is trying to handle these two cases. If the invocant is a class then ref($self) will return undef since a plain string (the class name) is not a reference. If the invocant is an object, then ref($self) will return the name of the class that the object is an instance of.
If you're trying to grok Perl's native support for OO programming then start with the standard tutorial doc. If you just want to do OO programming with Perl then start with Moose.

Is it a good practice in Perl when instance methods call each other over a "$self" reference?

Should instance methods in Perl call each other like this:
package BlaBla;
sub foo {
my($self) = #_;
#do something awesome;
}
sub bar {
my($self) = #_;
foo();
}
Or like this:
package BlaBla;
sub foo {
my($self) = #_;
#do something awesome
}
sub bar {
my($self) = #_;
$self->foo();
}
Thank you all for your time.
Yes, you should include $self - if you don't, polymorphism won't work because each method will look for all calls in its own package, even if they're overridden in a subclass. Worse, if the referenced method is inherited from a parent and not overridden in the current subclass, the program will die because it doesn't exist in that package. And that's even if you do remember to try to fake out Perl's OO mechanism by passing $self as the first parameter.
If foo() is a method that can be called from other places you should certainly always call it as a method, otherwise classes inheriting from you won't be able to override it, and you'll force your foo() to check if it's being called in a methody-way or in a functiony-way.
On the other hand, if foo() is just some helper code that a few of your methods use, and is quite specific to your implementation of the class, then you can call it directly, but should then really always call it directly, and might want to label it as a private function available to the class by prefixing its name with an underscore: _foo().
The first one won't work, assuming you use $self somewhere in foo(), because it's not getting any arguments passed. You could call foo($self), but you're almost certainly better off using actual method call syntax instead of throwing the OO features of Perl out the window and just treating foo() as a function that happens to call its first parameter "$self".
Yes, instance methods should call each other with $self - otherwise, in some cases you'll need to check the args of the method and figure out whether it's being called on $self or not, which will make your code messier for no reason.
Th first approach will not work as written.
sub bar {
my($self) = #_;
foo();
}
Here you are explicitly invoking foo as a function with no arguments via that foo(); statement. This will construct an empty local #_ array. The first statement in foo extracts $self as the first element from this local #_, so $self is undefined with this mechanism.
You need to pass $self as an argument to foo. There are (at least) five ways to do this:
Arrow notation: Invoke foo via $self->foo();
Indirect notation: Invoke foo via foo $self;
Normal subroutine invocation: Invoke foo via foo($self);
Implied arguments: Invoke foo via foo $self; This option can only used if foo has been predeclared with a function prototype.
Don't construct that local #_ array. Let foo piggyback on bar's #_ array. Invoke foo via &foo; Note that there are no parentheses in this invocation.
Regarding option #5: It does exist. Don't use it. It will get you into trouble.
The difference between #2 and #4 become apparent when foo takes additional arguments. The indirect notation becomes (for example) foo $self 42; while the implied form becomes foo $self, 42; The indirect notation (option 2) is now strongly discouraged. Options 3 and 4 are also discouraged for use with methods.
That leaves option #1. Even though the arrow notation is just syntactic sugar, it means a lot to the reader. Use it.

Perl function name clash

I'm in a situation where a module I'm using has a function whose name is exactly the same as one in my own module. When I try to call the function in my module (OO Perl, so $self->function) it's calling the function from the other module instead.
I've already got around it by renaming my function but as a matter of interest, is there any way of explicitly calling the function from my module?
edit:
this is essentially what I'm doing
package Provider::WTO;
use base qw(Provider); # Provider contains a method called date
use utilities::utils; #not my module so don't blame me for the horrendous name :-)
...
sub _get_location
{
my $self = shift;
return $self->date."/some_other_string"; # calls utilities::utils::date()
}
If the name conflict is caused by an import from another module you might consider either Sub::Import, which allows for easy renaming of imports, even if the exporting module doesn't explicitly support that, or namespace::autoclean/namespace::clean.
package YourPackage;
use Sub::Import 'Some::Module' => (
foo => { -as => 'moo' },
); # imports foo as moo
sub foo { # your own foo()
return moo() * 2; # call Some::Module::foo() as moo()
}
The namespace cleaning modules will only be helpful if the import is shadowing any of your methods with a function, not in any other case:
package YourPackage;
use Some::Module; # imports foo
use Method::Signatures::Simple
use namespace::autoclean; # or use namespace::clean -except => 'meta';
method foo {
return foo() * 2; # call imported thing as a function
}
method bar {
return $self->foo; # call own foo() as a method
}
1;
This way the imported function will be removed after compiling your module, when the function calls to foo() are already bound to the import. Later, at your modules runtime, a method called foo will be installed instead. Method resolution always happens at runtime, so any method calls to ->foo will be resolved to your own method.
Alternatively, you can always call a function by it's fully-qualified name, and don't import it.
use Some::Module ();
Some::Module::foo();
This can also be done for methods, completely disabling runtime method lookup:
$obj->Some::Module::foo();
However, needing to do this is usually a sign of bad design and you should probably step back a little and explain what you did to get you into this situation in the first place.
Do you need that subroutine from the offending module? Without knowing more about it, I think the quick fix is to explicitly not import it with an empty import list:
use Interfering::Module ();
If you need other imported things, you can specify the ones that you need:
use Interfering::Module qw(sub1 sub2);
If the list of exports you want is really long, you can just exclude the interfering subroutine:
use Interfering::Module qw(!bad_sub);
If none of those work, you'll have to say more about the interfering module.
Are you sure this is happening in a method call (i.e. $self->function) and not a regular call?
If that's the case, then the only way I can see of that happening is your module is extending the other module, and you're not defining the method in question, and the module you're extending defines a function with the same name as the method you're trying to call.
In any case, you can not import the offending function into your namespace with use Foreign::Module ().
If it's a regular function call that's getting clobbered, you can refer to it as Your::Module->function.

How can I check if I can call host() on a URI object in Perl?

I'm iterating through a list of links on a page, creating a URI object for each. When the URI object is created, I don't know whether the URL has a scheme, so when I later call $uri->host(), I will sometimes get
Can't locate object method "host" via package "URI::_generic" at -e line 1.
because the URI object is of type URI::_generic, and doesn't have a host() attribute.
I could check before object creation with regex, or I could wrap the $uri->host() call in an eval block to handle the exception, but I figure there has to be a more suave method than either of those.
My suggestion: use the built in language features to your advantage before a regex.
Instead of a regex, you can do this:
if ($uri->can('host')) {
say "We're good!";
}
...to see if it's available. You could also check it's type:
if ($uri->isa('URI::_generic')) {
die 'A generic type - not good!' ;
}
...and verify that you have one that's good.
The UNIVERSAL class (perldoc UNIVERSAL) is pretty useful indeed; it contains:
$obj->can( METHOD ), for determining if METHOD is available on the $obj class (or you can use a bare classname rather than a blessed object - used for duck typing!
$obj->isa( TYPE ), for determining if $obj is type TYPE or is descended from TYPE (essentially, checks if ref($obj) is in TYPE's #ISA array) (bare classname also allowed) - used for some polymorphic implementations
VERSION, for getting a module's version string (boorrrrring)