How do I get to these blessed variables? - perl

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

Related

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

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
}

Is possible to access ATTR for Perl packages without defining a getter?

I am currently working on a Perl 5.8 project.
I have package that looks like:
package Foo::Bar;
use strict;
use warnings;
use Class::Std;
our #EXPORT_SAFE = qw(Class::Std);
my %baz :ATTR;
sub BUILD {
my ($self, $ident, $args) = #_;
$baz{$ident} = $$args{something};
}
I am not exposing baz with any getter, but I would like to fetch it's content for unit testing purposes. There is any way to do it in Perl?
e.g. in Ruby you can some_instance.instance_variable_get("##{name}")
Thank you very much in advance
TL;DR
The answer in the general case is "it depends (but probably)".
The answer in your case is "no".
Detail
There is no fixed way to implement classes and objects in Perl. In most cases an object will be a blessed reference to a hash. In those cases, you could simply treat the object reference as a hash reference and look up the key directly. So, code like this:
my $baz = $obj->{baz};
However, you're not using the most common approach to building Perl objects, you're using Class::Std. And Class::Std does things rather differently. Class::Std uses an approach called "inside-out objects" which was popularised by Damian Conway in Object Oriented Perl and which was very fashionable for a while about twenty years ago.
In normal objects, you have a hash for each object. The keys are the attribute names and the values are the attribute values. With inside-out objects, each attribute has its own hash. The keys are the stringified references to an individual object and the value is the attribute's value for that object.
In effect, the "standard" approach is:
$object{attr} = value;
And the inside out approach is:
$attr{object} = value;
One of the big reasons why people liked inside-out objects is that the attribute hashes can be lexical variables stored in the class's source code. And that means they are truly private and cannot be accessed from outside of the class - except by using the provided accessor methods. Which is great if you want to force Perl to implement a far stronger kind of encapsulation. But terrible if you want to break through that encapsulation in the way that you do here.
So, no. In your case, you can't do this.
Class::Std could easily provide ->instance_variable_get, at least for variables that were given a name.[1] But it doesn't.
In the absence of something provided by Class::Std, you could add the following to your class:
use Carp qw( croak );
sub instance_variable_get {
my ($self, $name) = #_;
my $pkg_glob = do {
no strict qw( refs );
*{ __PACKAGE__ . "::" }
};
exists($pkg_glob->{$name})
or croak("Unknown attribute $name");
my $hash = *{ $pkg_glob->{$name} }{HASH}
or croak("Unknown attribute $name");
return $hash->{ident($self)};
}
Note that this requires using our instead of my for the hashes.
This will allow you to use
$some_instance->instance_variable_get('baz')
Of course, if you're using our for the hashes, you could also use
$Foo::Bar::baz{ $some_instance->ident }
Currently, :ATTR( :name<...> ), :ATTR( :init_arg<...> ), :ATTR( :get<...> ) and :ATTR( :set<...> ) provide a name for the attribute, though these all have other effects as well.

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.

Using sub reference with Moose builder

Moose documentation mentions that builder property for attribute in class definiton should be a string that contains name for function that will be called to build relevant attribute. Simple testing however shows that sub reference works as well:
has 'some_attribute' => (
is => 'ro',
lazy => 1,
builder => sub {
require SomeModule::Heavy;
return SomeModule::Heavy->new($_[0]);
},
);
Did I miss something in docs? Is usage of sub reference officially supported for builder?
Moose manual says:
You can also provide a subroutine reference for default. This reference will be called as a method on the object. […] As an alternative to using a subroutine reference, you can supply a builder method for your attribute. This has several advantages. First, it moves a chunk of code to its own named method, which improves readability and code organization. Second, because this is a named method, it can be subclassed or provided by a role.
So, if you use subroutine reference for builder then you lose these advantages. I think subroutine reference works as side effect and has no practical application.

Perl Classes, what is with Blessing Hashes?

I don't understand why a Perl constructor needs all this blessing, and why it is always done with a hash (it is possible to use other variable types, apparently).
How does it make any sense that a constructor would return a blessed reference to a hash when I create a new instance of a class? I could understand "return (this);" or something along those lines, but returning some other random variable just mystifies me (particularly when you are supposed to use a hash).
my ?var = new Test("foo");
package Test;
our $localvar;
sub new{
localvar = $_[1];
}
OK, so I have this basic class. I can set a class variable when I initialize it and then later use it like $var::localvar. But to have this actually compile and work in Perl I need to add in the line "return bless {}, shift;"???
It seems that this hash is sort of used as the instance of that class, with the methods being rather static. But you can still have class variables. It sounds like you are just linking a data object to a list of methods that take that object as a argument. But I am not sure why every tutorial would imply that you always use a hash if that was all that was happening. And I am confused why you have both this hash and any "our"s you declared in the class, they seem like mutually exclusive concepts?
It sounds like you are just linking a data object to a list of methods that take that object as a argument.
That's exactly what OO is, yes. The thing you return from the constructor is the instance. Unlike some other languages where the language creates a new "object instance" behind the scenes, and your constructor is just in charge of filling in slots, in Perl your constructor method gets to do the entire job. {} creates a reference to a new anonymous hash which will become the storage for the object, and bless is what actually turns that reference into an object, by tagging it with your class name.
But I am not sure why every tutorial would imply that you always use a hash if that was all that was happening.
A class can be any kind of reference, but a hash reference is the most useful and convenient, because hashes have named slots, so you can refer to your object's properties by name. There are examples out there of globref objects (filehandles and sockets), arrayref objects (rare, usually used for objects with only a few fields when the author is very concerned about speed and memory usage), and scalarref objects (often used to encapsulate a pointer returned by some C library). But hashref objects are "standard".
I can set a class variable when I initialize it and then later use it like ?var::localvar.
But why would you? Class variables are almost entirely useless, and there's no reason to bother with them until you have a grasp on more basic, and useful things.
How does it make any sense that a constructor would return a blessed reference to a hash when I create a new instance of a class?
Well, it would be a rather useless constructor if you didn't return the object you've created.
I could understand "return (this);" or something along those lines
Then what's the confusion? That's exactly what you should be returning. (Except the convention is to call it $self.)
sub new {
my ($class, ...) = #_;
my $self = bless({}, $class); # Or: my $self = $class->SUPER::new(...);
$self->{attribute1} = ...;
$self->{attribute2} = ...;
return $self;
}
It seems that this hash is sort of used as the instance of that class,
The blessed hash is the instance of that class aka the object.
Questions from the comments
Why do I have to [do my $self = bless({}, $class);] instead of just referencing the class instance. Like: $self = bless($class)
{} allocates a variable and bless associates it with a class. Two necessary steps in the creation of an object.
By having the two separate, you have the option of using different base variables for your object. For example, IO::Socket::INET uses a glob instead of a hash.
But most objects anyone would make would have no use for a hash in my opinion. A hash is a pretty specific data structure that is not needed or helpful for 99% of coding.
The point isn't to use a hash table; it's to use an associative array (where each element is an attribute).
Associative arrays (hash tables or otherwise) are both "needed and helpful" in far far more than 1% of coding.