Problem with mixins in a MooseX::NonMoose class - perl

Consider the following:
package MyApp::CGI;
use Moose;
use MooseX::NonMoose;
use Data::Dumper;
extends 'CGI::Application';
BEGIN {
print "begin isa = " . Dumper \#MyApp::CGI::ISA;
};
print "runtime isa = " . Dumper \#MyApp::CGI::ISA;
...
The output when this compiles is:
begin isa = $VAR1 = [
'Moose::Object'
];
runtime isa = $VAR1 = [
'CGI::Application',
'Moose::Object'
];
Why do I care? Because when I try to use a CGI::Application::Plugin::* class, it expects me to be inheriting from CGI::Application at compile-time already. The plugin class tries to call add_callback as a class method on my class, but can't, because my #ISA isn't set up yet.
What's the best way to solve this? Would tweaking #ISA manually in a BEGIN block interfere with MooseX::NonMoose?
Edit
The following appears to work, but I find it offensive:
package MyApp::CGI;
use Moose;
use MooseX::NonMoose;
use base 'CGI::Application';
extends 'CGI::Application';
I don't know enough (or anything, really) about Moose internals to know if this is a good idea.

I don't find use base 'CGI::Application'; extends 'CGI::Application'; to be terribly ghastly because it does precisely what you need:
At compile-time, #ISA contains 'CGI::Application', which exactly satisfies the usage requirements of CGI::Application::Plugin::*
At runtime, your class is a Moose descendant of CGI::Application, with all the ensuing benefits (being able to design the composition of your class with Moosey meta goodness). It's only after the extends 'CGI::Application' line is encountered that any work is done (i.e methods are called on your class) that rely on the work done by the extends statement: that your class descends from Moose::Object and you have a meta-class installed.
That said, jrockway's solution should also work:
BEGIN { extends 'CGI::Application' }
...where you get all the Moosey meta goodness just a little ahead of schedule from when you need it, and it shouldn't be too ahead of schedule, provided you already called use Moose and use MooseX::NonMoose in order to define extends.
(Addendum: Now I'm pondering the complilational complexities of creating the ability to force the parsing of a keyword at compile-time that are parsed immediately such as if they were wrapped in a BEGIN block. e.g. something like if Moose.pm declared use compiletime qw(extends). It would be a nice piece of syntactic sugar for sure.)

Related

Make package both Functional and OO

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.

Moose attribute default used even though subclass overrides the attribute

I'm tinkering with Moose as introduced in Intermediate Perl. I have an abstract class Animal with a property sound. The default behaviour should be to complain that sound has to be defined in subclasses:
package Animal;
use namespace::autoclean;
use Moose;
has 'sound' => (
is => 'ro',
default => sub {
confess shift, " needs to define sound!"
}
);
1;
A subclass has to do nothing else than define sound:
package Horse;
use namespace::autoclean;
use Moose;
extends 'Animal';
sub sound { 'neigh' }
1;
But testing this with
use strict;
use warnings;
use 5.010;
use Horse;
my $talking = Horse->new;
say "The horse says ", $talking->sound, '.';
results in
Horse=HASH(0x3029d30) needs to define sound!
If I replace the anonymous function in Animal with something simpler as in
has 'sound' => (
is => 'ro',
default => 'something generic',
);
things work fine. Why is that? Why is the default function executed even though I override it in the subclass?
There's two things in play here: How attributes are initialized and how accessors work.
Non-lazy ('eager') attributes are initialized when the class is instantiated. That's why you can actually leave off the
say "The horse says ", $talking->sound, '.';
and get the same error. If you make the attribute lazy, on the other hand, the error goes away. And that leads us to the real reason: the difference between attributes, accessors, and builders.
Animal has an attribute, sound, which is just a place that stores some data related to instances of the class. Because sound was declared ro, Animal also has a method that acts as an accessor, confusingly also called sound. If you call this accessor, it looks at the value of the attribute and gives it to you.
But this value exists independent of the accessor. The accessor provides a way to get at the value, but the actual existence of the value is dependent on the attribute's builder. In this case, the builder for the attribute is the anonymous method sub { confess shift, " needs to define sound!" }, and it will get run as soon as the attribute needs to have a value.
In fact, if you leave out the is => 'ro', you will stop Moose from creating an accessor at all, and the error will still pop at construction time. Because that's when your class builds the sound attribute.
When the attribute needs its value depends on whether you've declared it as lazy or not. Eager attributes are given their values on object construction. It doesn't matter if there's an accessor, the builder gets called when the object is created. And in this case, the builder dies.
Lazy attributes are given their values the first time they are needed. The default accessor tries to get the value of the attribute, which causes the builder to fire, which causes the script to die. When you override sound, you replace the default accessor with one that doesn't call the builder and therefore doesn't die anymore.
Does that mean you should make the sound attribute lazy? No, I don't think so. There's better mechanisms available, depending on what exactly you are trying to assert. If what you are trying to assert is that Animal->sound must be defined, you can use BUILD like so:
package Animal;
use namespace::autoclean;
use Moose;
has 'sound' => (is => 'ro');
sub BUILD {
my ($self) = #_;
confess "$self needs to define sound!"
unless defined $self->sound;
}
1;
During object construction, each of the parent classes' BUILD methods gets called, which lets them make assertions about object state.
If, on the other hand, what you wanted to assert is that a subclass has to have overridden sound, it's better not to make sound an attribute at all. Instead,
package Animal;
use namespace::autoclean;
use Moose;
sub sound {
confess "Abstract method `sound` called!";
}
1;

Extending a Non-Moose Class: Not a HASH reference at accessor

I'm Trying to extend a non-moose class, and when I call an accessor defined by moose for my extended class I'm getting the following error:
Not a HASH reference at accessor MyGraph::weight (defined at MyGraph.pm line 8) line 8
This is the simplified code:
package MyGraph;
use Moose;
use MooseX::NonMoose;
extends 'Graph';
has 'weight' => (
is => 'ro',
isa => 'Num',
);
no Moose;
__PACKAGE__->meta->make_immutable;
package main;
my $g = MyGraph->new;
$g->weight();
MooseX::NonMoose doesn't, out of the box, enable you to subclass a non-hashref class, and Graph uses an arrayref for its instances. The docs mention this, and suggest using MooseX::InsideOut to enable compatibility with non-moose classes that have other instance types.
The reference that the non-Moose class uses as its instance type must match the instance type that Moose is using. Moose's default instance type is a hashref.
Graph uses ARRAYREF as its instance type. MooseX::InsideOut is the solution.
package MyGraph;
use Moose;
use MooseX::InsideOut;
use MooseX::NonMoose;
extends 'Graph';
I've never done this but this looks like it might be what you want. http://metacpan.org/pod/MooseX::NonMoose

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 do Roles and Traits differ in Moose?

I have written a set of classes and interfaces that are implemented in Moose also using roles. What I am having trouble understanding is the exact differences in both usage and implementation of Moose traits vs. roles.
The Moose documentation states:
It is important to understand that roles and traits are the same thing. A role can be used as a trait, and a trait is a role. The only thing that distinguishes the two is that a trait is packaged in a way that lets Moose resolve a short name to a class name. In other words, with a trait, the caller can refer to it by a short name like "Big", and Moose will resolve it to a class like MooseX::Embiggen::Meta::Attribute::Role::Big.
It is my understanding that traits and roles are "the same". However, when implementing a basic test of the idea using the use Moose -traits 'Foo' syntax does not seem to do what I would expect. Surely I must be missing something here.
This first example fails with "Can't locate object method 'foo'"
package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
sub foo { warn 'foo' }
package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }
package MyApp::User;
use Moose -traits => 'HasTable';
__PACKAGE__->foo(); #Can't locate object method 'foo'
Compared to this one (which does work):
package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
sub foo { warn 'foo' }
package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }
package MyApp::User;
use Moose;
with 'MyApp::Meta::Class::Trait::HasTable';
__PACKAGE__->foo(); #foo
This is the only difference in how Moose uses the terms "Trait" and "Role".
Moose's documentation and APIs often use the term "traits" as "Roles applied
to Metaclasses". In your revised answer your first example applies the Role to
MyApp::User's metaclass via -traits, the second example applies it to the
class.
If you change your first example to:
package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
sub foo { warn 'foo' }
package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }
package MyApp::User;
use Moose -traits => 'HasTable';
__PACKAGE__->meta->foo();
You'll see "foo at [script]. line 3." Which is exactly what it supposed to
be doing.
UPDATE: Apparently I'm not exactly correct here. Traits are roles applied to instances. The -traits hook applies HasTable to the metaclass instance for MyApp::User. I have updated the relevant Moose docs.
You don't define a package 'x::Foo' with any role. Ripped straight from the documentation, we see that register_implementation returns the name of an actually defined package:
package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
has table => (
is => 'rw',
isa => 'Str',
);
package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }
package MyApp::User;
use Moose -traits => 'HasTable';
__PACKAGE__->meta->table('User');
The "shortcut" is achieved by Moose looking for "Moose::Meta::Class::Trait::$trait_name" (when called in a "class context"), not just passing back a shorter name.