PERL: ref, shift keyword [duplicate] - perl

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.

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

How to handle properties on a SCALAR based Perl class?

In Perl, it's easy to bless a hashref and use it to store and read properties:
package MyPackage;
use strict;
use warnings;
sub new {
bless {}, __PACKAGE__;
}
sub SomeProperty {
my $self = shift;
if (#_) {
return $self->{SomeProperty} = shift;
}
$self->{SomeProperty};
}
# Or even like this to be able to call $obj->OtherProperty = $x;
sub OtherProperty : lvalue {
my $self = shift;
$self->{OtherProperty};
}
But, I've seen some Classes (from different Perl modules) that, when dumped, show a simple scalar blessed:
$obj = bless( \$8756489, 'Some::Package' );
Yet, they have methods and properties. The methods I understand, any subroutine a package can call then will be called when asking a blessed $object->name. The part I'm not understanding is how they can store properties. Where are those properties being stored?
Several times they accept things like $obj->property = $x or $obj->property($x) and can be independent of other instances of the same Class. Where are those properties being stored?
I know that really depends on the underlying implementation of the Class, what it is doing or what it is interacting with, and that can actually answer the question several times (e.g. the object is just interfacing with another object or connection somewhere and only sending or quering values to it).
However, if there's a way for a scalar based object to store properties (like in a different concept or approach to class structure in Perl), I'd really like to know it.
Thanks in advance for any comments! :-)
Well, one way is to use inside-out objects. Another is to use an XS-based class, where the scalar stores the address of a C/C++ structure in which the properties are stored (this is normally done only when the class's purpose is to interface with a C/C++ library).
You could also do something weird like index parts of the scalar using substr or pack, but I doubt anybody's done that except to prove it could be done.

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.

Setting MooseX::Method::Signatures defaults to an instance variable

I have a set of methods where I would like the caller to be able to override a value, or it defaults to the instance variable.
So what I keep trying to do is:
method foo( Str :$blah = $self->blah ) {
#doStuff
}
which throws a parsing error so I end up doing this everywhere
method foo( Str :$blah? ) {
$blah = $self->blah unless defined $blah;
#doStuff
}
Not horrendous, but seems silly when MooseX::Method::Signatures supports the default concept and has fixed all my other standard 'start of method' lines.
Invariably when I'm trying to do something like this and I can't find anyone else on the web who's run into the same problems, I'm approaching the problem the wrong way. It seems like I might be trying to jam a functional program into a oo layout, rather than actual oo as the methods are more helper functions for calling externally rather than methods operating on the object. So just checking if I'm just defining it incorrectly or if what I'm doing is "dumb" or just not supported by Parse::Method::Signatures.
AFAIK The Signatures module hooks itself into the Perl parser and injects some code to handle the prototypes. It is remarkable that this works.
That said, using non-constant values as defaults could have issues. And there may be scenarios where calling some code to prepopulate a value could wreak havoc. Specifically, should the code that prepopulates the value should only be called if no value for the argument is given, or should it be always called? What should we do with side effects? What should the caller be? If I have a global $self object, shouldn't that receive the method call, as the scoping rules clearly dictate this? (As our $x=5; my $x=$x; is valid, but just my $x=$x is not). Even better, what would happen if the default value population method call would call the same method, but again without a value for the optional parameter?
You can always fall back to old-school optional parameters:
sub foo {
my ($self, $blah) = #_;
# something like my ($self, $blah) = (#_, $self->blah); wouldn't work, of course.
$blah //= $self->blah; # nicer than old `unless defined`
...;
}
or, in this case:
method foo (:$blah?) {
$blah //= $self->blah
}
I find this use of the defined-or operator quite enjoyable.

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.