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.
Related
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.
I've seen CPAN Perl modules that can be used in a functional or OO way. I usually write OO and Functional packages depending on what I need, but I'm still not how write modules that can used both ways.
Could somebody give me a simple example of a package that can be used in functional and/or OO way? I'm obviously interested in the pieces that allows the package be used both ways.
Thank you
A core example is File::Spec, which has a File::Spec::Functions wrapper. It's not so much object oriented but it does use the object oriented principle of inheritance, so its main API uses method calls, but it doesn't need to keep any state.
use strict;
use warnings;
use File::Spec;
use File::Spec::Functions 'catfile';
print File::Spec->catfile('/', 'foo', 'bar');
print catfile '/', 'foo', 'bar';
Another example is Sereal, whose encoder and decoder can be used both as objects or via exported functions which wrap them.
use strict;
use warnings;
use Sereal::Encoder 'encode_sereal';
my $data = {foo => 'bar'};
my $encoded = Sereal::Encoder->new->encode($data);
my $encoded = encode_sereal $data;
Sereal aside, it's usually good organizational practice to keep your object classes and your exporting modules separate. Especially don't try to have the same function be callable as a method or an exported function; the primary issue is that it's indistinguishable from the subroutine itself whether it was called as $obj->function('foo') or function($obj, 'foo'). As #choroba noted, CGI.pm tries to do this and it's a mess.
My WiringPi::API distribution is written in such a way. Note that in this case here, there's no state saving required, so if keeping state is a necessity, this way of doing it won't work as-is.
You can use it functionally:
use WiringPi::API qw(:all)
setup_gpio();
...
Or use its Object Oriented interface:
use WiringPi::API;
my $api = WiringPi::API->new;
$api->setup_gpio();
...
For functional, I use #EXPORT_OK, so that the user's namespace isn't polluted unnecessarily:
our #EXPORT_OK;
#EXPORT_OK = (#wpi_c_functions, #wpi_perl_functions);
our %EXPORT_TAGS;
$EXPORT_TAGS{wiringPi} = [#wpi_c_functions];
$EXPORT_TAGS{perl} = [#wpi_perl_functions];
$EXPORT_TAGS{all} = [#wpi_c_functions, #wpi_perl_functions];
...and a few example functions/methods. Essentially, we check the number of parameters coming in, and if there's an extra one (which would be the class/object), we manually just shift it out:
sub serial_open {
shift if #_ > 2;
my ($dev_ptr, $baud) = #_;
my $fd = serialOpen($dev_ptr, $baud);
die "could not open serial device $dev_ptr\n" if $fd == -1;
return $fd;
}
sub serial_close {
shift if #_ > 1;
my ($fd) = #_;
serialClose($fd);
}
sub serial_flush {
shift if #_ > 1;
my ($fd) = #_;
serialFlush($fd);
}
Typically I would do some parameter checking to ensure that we're shifting off the correct thing, but in testing, it was faster to allow the back end C/XS code worry about that for me.
As stated, there are a number of modules that do this and some have been named. A good practice is to write a separate module for the functional interface, that uses the class and exports its (select) functions.
But it is quite possible to have both interfaces in one package, with same method/function names, if there is a specific need for that. See the section at the end for one very specific and rare use case that wouldn't be handled by the following basic example, and for how to resolve it.
Here is a basic package that has both interfaces
package Duplicious; # having interfaces to two paradigms may be confusing
use warnings;
use strict;
use feature 'say';
use Scalar::Util qw(blessed);
use Exporter qw(import);
our #EXPORT_OK = qw(f1);
my $obj_cache; # so repeated function calls don't run constructor
sub new {
my ($class, %args) = #_;
return bless { }, $class;
}
sub f1 {
say "\targs in f1: ", join ', ', #_; # see how we are called
my $self = shift;
# Functional interface
# (first argument not object or class name in this or derived class)
if ( not ( (blessed($self) and $self->isa(__PACKAGE__))
or (not ref $self and $self->isa(__PACKAGE__)) ) )
{
return ($obj_cache || __PACKAGE__->new)->f1($self, #_);
}
# Now method definition goes
# ...
return 23;
}
1;
The caller
use warnings; # DEMO only --
use strict; # Please don't mix uses in the same program
use feature 'say';
use Duplicious qw(f1);
my $obj = Duplicious->new;
say "Call as class method: ";
Duplicious->f1("called as class method");
say "Call as method:";
my $ret_meth = $obj->f1({}, "called as method");
say "\nCall as function:";
my $ret_func = f1({}, "called as function");
Output
Call as class method:
args in f1: Duplicious, called as class method
Call as method:
args in f1: Duplicious=HASH(0x21b1b48), HASH(0x21a8738), called as method
Call as function:
args in f1: HASH(0x21a8720), called as function
args in f1: Duplicious=HASH(0x218ba68), HASH(0x21a8720), called as function
The function call dispatches to the method, thus two lines (note arguments).
I find it in principle awkward to use Exporter in a module that defines a class (but I am not aware of any actual problems with doing it); it results in a potentially confusing interface. This on its own is a good reason to separate interfaces so that the functional one has to load a specific module.
There is also one detail that requires attention. The method call
($obj_cache || __PACKAGE__->new)->f1(...)
uses the cached $obj_cache (if this sub has been called already) to make the call. Thus the object's state is kept, that may or not have been manipulated in the previous calls to f1.
That is rather non-trivial in a call meant to be used in a non object-oriented context and should be carefully investigated. If there are issues just drop that cacheing or expand it into a full if statement where the state can be reset as needed.
These two uses should absolutely not be mixed in the same program.
To test with a derived class I use the minimal
package NextDupl;
use warnings;
use strict;
use feature 'say';
use parent 'Duplicious';
1;
and add to the main program above the following
# Test with a subclass (derived, inherited class)
my $inh = NextDupl->new;
say "\nCall as method of derived class";
$inh->f1("called as method of derived class");
# Retrieve with UNIVERSAL::can() from parent to use by subclass
my $rc_orig = Duplicious->can('f1');
say "\nCall via coderef pulled from parent, by derived class";
NextDupl->$rc_orig("called via coderef of parent by derived class");
The additional output is
Call as method of derived class
args in f1: NextDupl=HASH(0x11ac720), called as method of derived class
Call via coderef pulled from parent, by derived class
args in f1: NextDupl, called via coderef of parent by derived clas
This incorporates a test using UNIVERSAL::can, as it came up in a comment.
There is one specific limitation (that I am aware of), raised and discussed in comments.
Imagine that we write a method that takes an object (or a class name) as its first argument, so to be invoked as ->func($obj); further – and this is what matters – this method allows any class as it works in a way that doesn't care what class it has. This would be very particular, but it is possible and it raises the following problem.
The function call corresponding to this method would be func($obj), and when $obj happens to be in the hierarchy of this class that would result in the method call ->func(), incorrectly.
There is no way to disambiguate this in the code that decides on whether
it's called as a function or as a method, since all it does is it looks at the first argument. If it's an object/class in our own hierarchy it decides that this was a method call on that object (or a class method call), and in this particular case that is wrong.
There are two simple ways, and possibly another one, for the module's author to settle this
Do not provide the functional interface for this highly specific method
Give it a separate (clearly related) name
The if condition that decides how we are called, by checking the first argument, is canned but still written for every method that has that interface. So in this method check one more argument: if the first one is object/class of this class and the next is (any) object/class then it's a method call. This does not work if that second argument is optional.
All this is completely reasonable. In a class that exercises its defining trait, to have and use data ("attributes"), there will likely be methods that cannot be translated into function calls. This is because a single program should only use one interface, and with functions there is no state so methods that rely on it won't fly. (Use of a cached object for this is highly treacherous.)
So one will always have to decide carefully about the interface, and to pick and choose.
Thanks to Grinnz for comments.
Note that there is a completely different paradigm of "functional programming," and the title leaves that a little unclear. All this is about the functional interface in a procedural approach.
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 possible to get a subroutine reference from a Moose object in Perl? For example:
package A;
use Moose;
1;
sub mm {
print "Hello\n";
}
Then I make an A object:
use warnings;
use strict;
use A;
my $o=A->new();
my $sub=\&{$o->mm};
$sub->();
This does not work. It gives error:
Undefined subroutine &main::1
If I know that $o is an A object, I can of course solve this using my $sub=\&A::mm; instead.
But in the case, where I am only given $o is it possible to extract the reference to a function mm ?
The code you're using calls $o->mm and treats the result as a sub reference (symbolic or otherwise), dereferences it, and creates a new reference to it.
If you want a sub that calls $o->mm, you'll need to make one.
my $sub = sub { $o->mm };
Or if the args received by the sub are supposed to be passed to $o->mm,
my $sub = sub { $o->mm(#_) };
Taking references of methods goes against the grain of object-oriented design, but you can do it just fine if you use UNIVERSAL::can. UNIVERSAL is the ultimate base class from which everything inherits, and it is defined implicitly for every Perl program.
Leave your module as it is (although the use Moose is having no effect at present) and change your program to this
use strict;
use warnings;
use A;
my $o = A->new;
my $sub = $o->can('mm');
$sub->();
output
Hello
But do remember that a method will normally have been written to expect either the class/package name (for a class method) or an object reference (for an object method) as its first parameter.
Since this way circumvents Perl's method call syntax, you would have to do it yourself, so the call should look like
$sub->($o)
although in this case mm isn't a real method so it doesn't care what you pass to it.
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.