NAME
Perlmazing::Engine - Have your functions load their code and associated modules only when needed, automagically.
SYNOPSIS
This module was written with one main goal in mind: to save time, processing and memory when a module is loaded and it has a lot of functions (exported or not) and a those functions require loading a lot of other modules.
By using this module, you can write your functions in separate files without having to declare any package. Perlmazing::Engine will create empty symbols for each function you write (one per file). Those symbols will be present in your own module just like if they were regular functions - but the code associated with them will be loaded the first time you attempt to use each function. For many heave modules, this can be the answer to faster loading times and, when not all functions are used by a script, also a lot of processing and memory can be saved.
Also, behind the scenes, Perlmazing::Engine manages each function in a separate and unique namespace, but making any other function from your module visible and usable just like if they were all in the same namespace. By doing this, it also maintains your namespace clean, free from anything a specific function imports from other modules just to work itself. Each function can have it's own globals (variables, secondary functions, etc.) without poluting the whole module.
In order to use Perlmazing::Engine, you just do something like the following:
package MyModule;
use Perlmazing::Engine;
# Now your functions are usable, but not loaded until called.
1;
HOW TO USE
So, where do we put functions and their code so Perlmazing::Engine knows what to do? You need to have the following structure for your module files. Assume your module name is MyModule
; so you will organize any submodules in the folder ./Submodule
, like normal, but you will also have a ./MyModule/Perlmazing
folder where your function files will live. You can have an optional ./MyModule/Perlmazing/Precompile
folder, where you will place function files that for any reason you want to be compiled at compile time (e.g. functions with prototypes):
.
|-- MyModule.pm
+-- MyModule/
+-- Perlmazing/
|-- function_A.pm
|-- function_B.pm
+-- Precompile/
|-- function_C.pm
|-- function_D.pm
In the previous example, Perlmazing::Engine will create empty symbols for the functions function_A
, function_B
, function_C
and function_D
, all of them belonging to the MyModule
namespace. If you had a submodule called MyModule::Clients
and wanted to use Perlmazing::Engine
there too, then that submodule would use its own folder at ./MyModule/Clients/Perlmazing
. It would then look like this:
.
|-- MyModule.pm
+-- MyModule/
|-- Clients.pm
+-- Clients/
| +-- Perlmazing
| |-- function_E.pm
| |-- function_F.pm
+-- Perlmazing/
|-- function_A.pm
|-- function_B.pm
+-- Precompile/
|-- function_C.pm
|-- function_D.pm
MyModule::Clients
is now able to use the functions function_E
and function_F
by just calling use Perlmazing::Engine
.
HOW FUNCTIONS SHOULD BE WRITTEN
Besides residing on its own file in their respective Perlmazing
folder, and having a file name that is their exact actual function name, they also have one particularity that most be respected: the function name inside the file will always be main
. This has several reasons, being one of the most important ones that you can import your own module and if that module exports functions by default, and one of those functions happens to be the one you are writting in this file, then having the same exact name would cause a conflict.
There are also two types of functions you can write, in terms of behavior and this is something comming from Perlmazing::Engine. Basically, you get the regular type and the Listable
type. The regular type is simply any kind of subroutine, and it can simply do whatever you code it to do.
REGULAR FUNCTIONS
The following is an example of a simple function. Let's say that function name is "say_hello()", so it will live in the file ./MyModule/Perlmazing/say_hello.pm
and will have the following content:
use strict;
use warnings;
# use any other module you need here for this specific function to work
sub main {
print "Hello there!\n";
}
1;
LISTABLE FUNCTIONS
Listable
functions are all meant to follow this behavior:
# Assume 'my_sub' is a function of the type Listable:
# Calling my_sub on an array will directly affect elements of @array:
my_sub @array;
# Calling my_sub on a list will *attempt* to directly affect the
# elements of that list, failing on 'read only'/'constant' elements
# like the elements in the following list:
my_sub (1, 2, 3, 4, 5, 'string element');
# Calling my_sub on an array or a list BUT with an assignment,
# will *not* affect the original array or list, but assign an
# affected copy:
my @array_A = my_sub @array;
my @array_B = my_sub (1, 2, 3, 4, 5, 'string_element');
# Listable functions can be chained to achieve both behaviors
# (assignment or direct effect) on a single call. Assume
# 'my_sub2', 'my_sub3' and 'my_sub4' are also Listable functions:
my_sub my_sub1 my_sub2 my_sub3 my_sub4 @array;
my @array_C = my_sub my_sub1 my_sub2 my_sub3 my_sub4 (1, 2, 3, 4, 5, 'string element');
# When a Listable function is assigned in scalar context, then only the
# first element is assigned, not a list/array count.
my $scalar = my_sub @array; # $scalar contains the first element of the resulting list
When writting a listable function, you need to do two things: first, make that function listable
by including in its <@ISA> the namespace Perlmazing::Listable
. Second, you should always deal directly with the argument $_[0]
and not a copy of it. This means you should not do something like my ($arg1, $arg2) = @_
. You will only deal with $_[0]
because Perlmazing::Engine
will always pass only one argument to Perlmazing::Listable
functions and expect that function to directly affect that argument. Then Perlmazing::Engine
will be the one deciding what to do with that result, based on the context and arguments that function was called with.
The following is an example taken from the function escape_uri
from the Perlmazing module. Look at how simple it is:
use Perlmazing;
use URI::Escape;
our @ISA = qw(Perlmazing::Listable);
sub main {
$_[0] = uri_escape($_[0]) if defined $_[0];
}
1;
That function will have all the behavior previously described for Listable
functions, but you don't need to think of that behavior here, Perlmazing::Engine
will do that for you and you will only work with $_[0]
.
EXPORTS
Perlmazing::Engine
doesn't export anything by default. In fact, so far none of its functions or methods are meant to be imported. If you are wondering about how to export functions from your own module (even if they work through Perlmazing::Engine
), then you will do so exactly as you would if you weren't using this module (e.g. using Exporter or your favorite export module/method).
METHODS
The following is a list of methods you can call from Perlmazing::Engine
:
found_symbols
my @symbols = Perlmazing::Engine->found_symbols($optional_namespace)
This method will return a list with all the symbols Perlmazing::Engine
found for a specific package/namespace. If you don't provide any arguments, then the current namespace will be used. The following is an example of it being used to export every function from your module into its caller:
use strict;
use warnings;
use Perlmazing::Engine;
require Exporter;
our @EXPORT = Perlmazing::Engine->found_symbols;
# Or, you could do that with @EXPORT_OK just to make them available for export.
loaded_symbols
my @symbols = Perlmazing::Engine->loaded_symbols($optional_namespace)
This method will return a list of the symbols for which its actual code has been already loaded.
preload
Perlmazing::Engine->preload(@list_of_symbols_to_preload)
This method will load (completely, including their respective code) all of the symbols passed as argument. This is useful then you know you will need these symbols loaded from the begining, or maybe at compile time, for any reasons you may have.
precompile
Perlmazing::Engine->precompile
This method is similar to preload
, but while preload
works with any symbol name passed as argument, precompile
works with the symbols found in the precompile folder described previously.
AUTHOR
Francisco Zarabozo, <zarabozo at cpan.org>
BUGS
Please report any bugs or feature requests to bug-perlmazing at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Perlmazing. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Perlmazing::Engine
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
LICENSE AND COPYRIGHT
Copyright 2015 Francisco Zarabozo.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.