>
> This RFC proposes a minimal efficient well-scaling mechanism for
exporting.
> Only export of subroutines and tags are supported by this mechanism.
>
Though I'm not completely sure how the implementation works in other
compiled languages, I rather like the C, Java, Python method where just
about everything can be exported / imported.
Currently we have:
do "path-to-file";
Which essentially is an include
require {module-name} {optional-version-number} ;
caches includes.
use {module-name} {ver} (import list);
Which is compiled as:
BEGIN {
require {ver} {mod};
mod->import( import list );
}
This has the advantage of taking care of module compilation errors ahead of
time, in addition, it gives import the opportunity to extend the local
name-space based on the import list.
I'm sure the Exporter module was an evolutionary process. But what is the
advantage of a user defined importer over a direct compiler implemented
name-space adopter. Namely, why not make the built-in importer allow symbol
export. Namely, move and optimize the perl-based Exporter code into C code.
More importantly, remove the use of @EXPORT and @EXPORT_OK from the default
import behavior (though you can still use the old Exporter code for
compatibility). Simply allow any defined symbols to be exportable as would
be in other languages. In Python, any defined function is fair game for
module reuse. In perl, you can always just explicitly qualify the module
name for any given function call, so there is no advantage to not allowing
any function to be imported.
By moving code into C, you have massive performance benifits. By removing
the need compare two or more arrays ( @EXPORT_OK and @{IMPORT_ARGS} ), you
get even more.
Obviously, the most needed performance boost is in something like CGI.pm,
which doesn't want to compile everything all at once, and must base the
loading of the _DATA_ section on the import list. The process for this type
of activity would be the following:
our %code_set_a = ( func1 => 1, func2 => 1, func3 => 1 .. , :all => 1,
:standard => 1)
our %code_set_b = ( func4 => 1, func 5 => ... , :all => 1)
sub import {
my ( $load_a, $load_b.. );
for ( @_ ) {
$load_a = 1 if exists $code_set_a{ $_ };
$load_b = 1 if exists $code_set_b( $_ };
}
load_code_set_a if $load_a;
load_code_set_b if $load_b;
CORE::import( @_ ); # import has to ignore any invalid symbols
}
sub load_data {
our $data_loaded;
return if $data_loaded;
our $data_block = join ("", <DATA>);
eval $data_block;
$data_loaded = 1;
}
sub load_code_set_a {
load_data;
eval $CODE_SET_A;
}
sub load_code_set_b {
load_data;
eval $CODE_SET_B;
}
_DATA_
$CODE_SET_A <<EOS
sub func1 ..
sub func2 ..
EOS
$CODE_SET_B<<EOS
sub func4 ..
sub func5 ..
EOS
-Michael