mysubs - lexical subroutines
package MyPragma; use base qw(mysubs); sub import { my $class = shift; $class->SUPER::import( foo => sub { ... }, chomp => \&mychomp ); }
#!/usr/bin/env perl { use MyPragma; foo(...); chomp ...; } foo(...); # error: Undefined subroutine &main::foo chomp ...; # builtin
mysubs is a lexically-scoped pragma that implements lexical subroutines i.e. subroutines whose use is restricted to the lexical scope in which they are imported or declared.
mysubs
The use mysubs statement takes a list of key/value pairs in which the keys are subroutine names and the values are subroutine references or strings containing the package-qualified names of the subroutines. In addition, mysubs options may be passed.
use mysubs
The following example summarizes the type of keys and values that can be supplied.
{ use mysubs foo => sub ($) { ... }, # anonymous sub value bar => \&bar, # code ref value chomp => 'main::mychomp', # sub name value dump => '+Data::Dump::dump', # load Data::Dump 'My::foo' => \&foo, # package-qualified sub name -autoload => 1, # load modules for all sub name values -debug => 1 # show diagnostic messages ; foo(...); # OK prototype('foo') # '$' My::foo(...); # OK bar; # OK chomp ...; # override builtin dump ...; # override builtin } foo(...); # error: Undefined subroutine &main::foo My::foo(...); # error: Undefined subroutine &My::foo prototype('foo') # undef chomp ...; # builtin dump ...; # builtin
mysubs options are prefixed with a hyphen to distinguish them from subroutine names. The following options are supported:
If the value is a package-qualified subroutine name, then the module can be automatically loaded. This can either be done on a per-subroutine basis by prefixing the name with a +, or for all named values by supplying the -autoload option with a true value e.g.
+
-autoload
use mysubs foo => 'MyFoo::foo', bar => 'MyBar::bar', baz => 'MyBaz::baz', -autoload => 1; or use MyFoo; use MyBaz; use mysubs foo => 'MyFoo::foo', bar => '+MyBar::bar', # autoload MyBar baz => 'MyBaz::baz';
The -autoload option should not be confused with lexical AUTOLOAD subroutines, which are also supported. e.g.
AUTOLOAD
use mysubs AUTOLOAD => sub { ... }; foo(); # OK - AUTOLOAD bar(); # ditto baz(); # ditto
A trace of the module's actions can be enabled or disabled lexically by supplying the -debug option with a true or false value. The trace is printed to STDERR.
-debug
e.g.
use mysubs foo => \&foo, bar => sub { ... }, -debug => 1;
mysubs::import can be called indirectly via use mysubs or can be overridden by subclasses to create lexically-scoped pragmas that export subroutines whose use is restricted to the calling scope e.g.
mysubs::import
Client code can then import lexical subs from the module:
The import method is implemented as a wrapper around import_for.
import
import_for
mysubs methods are installed and uninstalled for a particular client of the mysubs library. Typically, this client is identified by its class name i.e. the first argument passed to the mysubs::import method. Note: if mysubs->import is called implicitly (via use mysubs ...) or explicitly, then the client identifier is "mysubs" i.e. mysubs can function as a client of itself.
mysubs->import
use mysubs ...
The import_for method allows an identifier to be specified explicitly without subclassing mysubs e.g.
package MyPragma; use base qw(Whatever); # we can't/don't want to subclass mysubs use mysubs (); # don't import anything sub import { my $class = shift; $class->SUPER::import(...); # call Whatever::import mysubs->import_for($class, foo => sub { ... }, ...); }
The installed subs can then be uninstalled by passing the same identifier to the unimport_for method.
unimport_for
Note that the import_for identifier has nothing to do with the package the lexical subs will be installed into. Lexical subs are always installed into the package specified in the package-qualified sub name, or the package of the currently-compiling scope.
mysubs->import is implemented as a call to mysubs->import_for i.e.
mysubs->import_for
package MyPragma; use base qw(mysubs); sub import { my $class = shift; $class->SUPER::import(foo => sub { ... }); }
- is equivalent to:
package MyPragma; use mysubs (); sub import { my $class = shift; mysubs->import_for($class, foo => sub { ... }); }
mysubs::unimport removes the specified lexical subs from the current scope, or all lexical subs if no arguments are supplied.
mysubs::unimport
use mysubs foo => \&foo; { use mysubs bar => sub { ... }, baz => 'Baz::baz'; foo ...; bar(...); baz; no mysubs qw(foo); foo ...; # error: Undefined subroutine &main::foo no mysubs; bar(...); # error: Undefined subroutine &main::bar baz; # error: Undefined subroutine &main::baz } foo ...; # ok
Unimports are specific to the class supplied in the no statement, so pragmas that subclass mysubs inherit an unimport method that only removes the subs they installed e.g.
no
unimport
{ use MyPragma qw(foo bar baz); use mysubs quux => \&quux; foo; quux(...); no MyPragma qw(foo); # unimports foo no MyPragma; # unimports bar and baz no mysubs; # unimports quux }
As with the import method, unimport is implemented as a wrapper around unimport_for.
This method complements the import_for method. i.e. it allows the identifier for a group of lexical subs to be specified explicitly. The identifier should match the one supplied in the corresponding import_for method e.g.
package MyPragma; use mysubs (); sub import { my $class = shift; mysubs->import_for($class, foo => sub { ... }); } sub unimport { my $class = shift; mysubs->unimport_for($class, @_); }
As with the import_for method, the identifier is used to refer to a group of lexical subs, and has nothing to do with the package from which those subs will be uninstalled. As with the import methods, the unimport methods always operate on (i.e. uninstall lexical subs from) the package in the package-qualified sub name, or the package of the currently-compiling scope.
Lexical subs cannot be called by symbolic reference e.g.
This works:
use mysubs foo => sub { ... }, AUTOLOAD => sub { ... } ; my $foo = \&foo; foo(); # OK - named bar(); # OK - AUTOLOAD $foo->(); # OK - reference
This doesn't work:
use mysubs foo => sub { ... }, AUTOLOAD => sub { ... } ; my $foo = 'foo'; my $bar = 'bar'; no strict 'refs'; &{$foo}(); # not foo &{$bar}(); # not AUTOLOAD
1.14
Sub::Lexical
Method::Lexical
chocolateboy <chocolate@cpan.org>, with thanks to mst (Matt S Trout), phaylon (Robert Sedlacek), and Paul Fenwick for the idea.
Copyright (C) 2008-2011 by chocolateboy
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.
To install mysubs, copy and paste the appropriate command in to your terminal.
cpanm
cpanm mysubs
CPAN shell
perl -MCPAN -e shell install mysubs
For more information on module installation, please visit the detailed CPAN module installation guide.