MOP4Import::Declare - map import args to $meta->declare_...() pragma methods.
$meta->declare_...()
#------------------- # To implement an exporter with MOP4Import::Declare, # just use it in YourExporter.pm "as base" like following: package YourExporter { use MOP4Import::Declare -as_base; # "use strict" is turned on too. use MOP4Import::Util qw/globref/; # encapsulates "no strict 'refs'". # This method implements '-foo' pragma, # and adds method named 'foo()' in $callpack. sub declare_foo { my ($myPack, $opts, $callpack) = @_; *{globref($callpack, 'foo')} = sub (@) { join("! ", "FOOOOOO", @_) }; } # This method implements [bar => $x, $y, @z] pragma, # and adds variables $bar, %bar and @bar in $callpack. sub declare_bar { my ($myPack, $opts, $callpack, $x, $y, @z) = @_; my $glob = globref($callpack, 'bar'); *$glob = \ $x; *$glob = +{bar => $y}; *$glob = \@z; } }; 1 #------------------- # Then you can use above from command line like: % perl -MYourExporter=-foo -le 'print foo bar => 3' FOOOOOO! bar! 3 % #------------------- # Or in another file: package MyApp; use YourExporter -foo, [bar => "A", "x", 1..3]; # Above means you called: # use strict; # use warnings; # YourExporter->declare_foo($opts, 'MyApp'); # YourExporter->declare_bar($opts, 'MyApp', "A", "x", 1..3); print "scalar=$bar\t", "hash=$bar{bar}\t", "array=@bar\n"; # So, you will get: # scalar=A hash=x array=1 2 3
MOP4Import::Declare is one protocol implementation of MOP4Import family. You can use this module to implement your own exporter in an extensible way.
With MOP4Import::Declare, arguments of import() are mapped into method calls starting with declare_...().
declare_...()
import() method of MOP4Import::Declare briefly does following:
import()
sub import { my ($myPack, @pragma) = @_; my $callpack = caller; $myPack->dispatch_declare(+{}, $callpack, -strict, @pragma); }
dispatch_declare() dispatches declare_PRAGMA() pragma handlers based on each pragma argument types (string, arrayref or coderef).
declare_PRAGMA()
use YourExporter -PRAGMA;
-Identifier, word starting with -, is dispatched as:
-Identifier
-
$myPack->declare_PRAGMA($opts, $callpack);
Note: You don't need to quote this pragma because perl has special support for this kind of syntax (bareword lead by -).
use YourExporter [PRAGMA => @ARGS];
ARRAY ref is dispatched as:
$myPack->declare_PRAGMA($opts, $callpack, @ARGS);
use YourExporter qw/NAME *NAME $NAME %NAME @NAME &NAME/;
These kind of words (optionally starting with sigil) just behaves as ordinally export/import.
use YourExporter sub { ... };
You can pass callback too.
sub { my ($yourExporterPackage, $opts, $callpack) = @_; # do rest of job }
All pragmas below are actually implemented as "declare_PRAGMA" method, so you can override them in your subclass, as you like.
This pragma turns on use strict; use warnings;.
use strict; use warnings;
This pragma turns on use warnings qw(FATAL all NONFATAL misc);.
use warnings qw(FATAL all NONFATAL misc);
[base => CLASS...]
Establish an ISA relationship with base classes at compile time. Like base, this imports %FIELDS from base classes too.
%FIELDS
Note: when target module uses c3 mro, this pragma adds given classes in front of @ISA.
@ISA
[parent => CLASS...]
Establish an ISA relationship with base classes at compile time. In addition to "base", this loads requested classes at compile time, like parent.
[as_base => FIELD_SPECs...]
This pragma sets YourExporter as base class of target module. Optional arguments are passed to "fields" in fields pragma.
Note: as noted in "base", this pragma cares mro of target module. You can simply inherit classes with "generic" to "specific" order.
[fields => SPEC...]
This pragma adds %FIELDS definitions to target module, based on given field specs. Each fields specs are either single string or array ref like [FIELD_NAME => SPEC => value, ...].
[FIELD_NAME => SPEC => value, ...]
use MOP4Import::Declare [fields => qw/ foo bar baz / ]; use MOP4Import::Declare [fields => [debug => doc => 'debug level'], [dbi_dsn => doc => 'DBI connection string'], qw/dbi_user dbi_password/ ];
For more about fields, see whyfields.
You can define special hook for field spec. That should named starting with declare___field_with_....
declare___field_with_...
sub declare___field_with_foo { (my $myPack, my $opts, my $callpack, my FieldSpec $fs, my ($k, $v)) = @_; $fs->{$k} = $v; # Do other jobs... }
When field bar in class Foo has spec default => $VALUE, method Foo::default_bar is defined with $VALUE.
bar
Foo
default => $VALUE
Foo::default_bar
sub Foo::default_bar { $VALUE }
If VALUE is CODE ref, it is directly assigned to method symbol.
Note: This spec only cares about defining above default_... method. To make default value assignment really work, you must have constructor which cooperate well with this. You can use MOP4Import::Base::Configure for that purpose but are not restricted to it. Anyway MOP4Import::Declare itself will be kept constructor agnostic.
default_...
[constant => NAME => VALUE]
use YourExporter [constant => FOO => 'BAR', or_ignore => 1];
This pragma adds constant sub NAME to target module.
NAME
or_ignore => BOOL
If this option is given and given NAME already defined in target module, skip adding.
This pragma adds target module to %INC so that make the module require safe.
%INC
require
[map_methods => [FROM => TO]...]
This pragma looks up actual sub of TO and set it to target module with name FROM. For example:
TO
FROM
package MyStore { use MOP4Import::Declare [parent => qw/Plack::Session::Store::File/] , [map_methods => [get => 'fetch'], [set => 'store']]; } use Plack::Builder; builder { enable 'Session::Simple', store => MyStore->new(dir => $sess_dir); $app };
This implements MOP4Import::Declare style type-based pragma dispatching.
MOP4Import::Declare
YourExporter->dispatch_declare($opts, $callpack, -foo, [bar => 'baz'], '*FOO');
is same as
YourExporter->declare_foo($opts, $callpack); YourExporter->declare_bar($opts, $callpack, 'baz'); YourExporter->dispatch_import($opts, $callpack, '*FOO');
This mimics Exporter like sigil based import. Actually this dispatches import_... method with respect to leading sigil. (This means you can override each cases in your subclass). If $STRING has no sigil, "import_NAME" will be called.
import_...
$STRING
use YourExporter qw/*FOO $BAR @BAZ %QUX &QUUX/;
BEGIN { YourExporter->import_GLOB(+{}, $callpack, GLOB => 'FOO'); YourExporter->import_SCALAR(+{}, $callpack, SCALAR => 'BAR'); YourExporter->import_ARRAY(+{}, $callpack, ARRAY => 'BAZ'); YourExporter->import_HASH(+{}, $callpack, HASH => 'QUX'); YourExporter->import_CODE(+{}, $callpack, CODE => 'QUUX'); }
Note: some complex features like export list @EXPORT, @EXPORT_OK and :TAG based import are not implemented.
@EXPORT
@EXPORT_OK
:TAG
If you really want to implement those features, you can inherit this module and simply override dispatch_import. It will be called for all non reference pragmas.
dispatch_import
This method (hook) is called when simple word (matches /^\w+$/) is given as import list.
/^\w+$/
use YourExporter qw/FOO/;
is same as:
BEGIN { YourExporter->import_NAME(+{}, __PACKAGE__, 'Foo'); }
Actual implementation of import_GLOB, import_SCALAR, import_ARRAY, import_CODE.
import_GLOB
import_SCALAR
import_ARRAY
import_CODE
This type of object is always given as a second argument of each invocation of declare_PRAGMA. This object carries complex info such as caller filename, lineno to each pragma handlers. In simple cases, you don't need to care about these.
declare_PRAGMA
Note: field names of this type are about to change, so please do not rely them for now.
fields pragma in this module creates this type of object for each field specs. Currently, only name, doc and default are declared. But you can extend FieldSpec in your exporter like following:
name
doc
default
use YourBaseObject { use MOP4Import::Declare -as_base; use MOP4Import::Types FieldSpec => [[fields => qw/readonly required validator/]]; } package MyApp { use YourBaseObject -as_base, [fields => [app_name => readonly => 1, required => 1]] }
KOBAYASHI, Hiroaki <hkoba@cpan.org>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install MOP4Import::Declare, copy and paste the appropriate command in to your terminal.
cpanm
cpanm MOP4Import::Declare
CPAN shell
perl -MCPAN -e shell install MOP4Import::Declare
For more information on module installation, please visit the detailed CPAN module installation guide.