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