Home > Mobile >  How can I export a subroutine from a Moose package?
How can I export a subroutine from a Moose package?

Time:03-21

How can I export a normal, non-OO subroutine from a Moose package? In a regular package, I'd do it with Exporter, @ISA and @EXPORT.

CodePudding user response:

Moose is for building classes and roles. While you technically can also export functions, it's not necessarily the best idea.

Here's an example Moose class which also exports a function.

MyApp/Widget.pm

use v5.26;
use warnings;

package MyApp::Widget;

use Exporter qw( import );
our @EXPORT_OK = qw( is_widget );

use Moose;
use namespace::autoclean -except => 'import';

has name => ( is => 'ro', isa => 'Str', required => 1 );

sub is_widget {
    my $object = shift;
    blessed( $object ) and $object->isa( __PACKAGE__ );
}

__PACKAGE__->meta->make_immutable;

Here's how you might use it:

use v5.26;
use warnings;
use MyApp::Widget qw( is_widget );

my $w = 'MyApp::Widget'->new( name => 'Foo' );
say is_widget( $w );
say $w->is_widget;

Note that even though is_widget was intended an exportable function, it can also be called as a method! In this case, that's a feature rather than a bug, but often that will be an inconvenience.

A better idea might be to create two separate packages: one for your class and one for your exportable functions.

MyApp/Widget.pm

use v5.26;
use warnings;

package MyApp::Widget;

use Moose;
use namespace::autoclean;

has name => ( is => 'ro', isa => 'Str', required => 1 );

__PACKAGE__->meta->make_immutable;

MyApp/Util.pm

use v5.26;
use warnings;

package MyApp::Util;

use Exporter qw( import );
our @EXPORT_OK = qw( is_widget );

use Scalar::Util qw( blessed );

sub is_widget {
    my $object = shift;
    blessed( $object ) and $object->isa( 'MyApp::Widget' );
}

1;

And you'd call use your packages like this:

use v5.26;
use warnings;
use MyApp::Widget;
use MyApp::Util qw( is_widget );

my $w = 'MyApp::Widget'->new( name => 'Foo' );
say is_widget( $w );

Because the Moose class and the Exporter are now cleanly separated, you can no longer call $w->is_widget — it's entirely a function and no longer a method.

  • Related