package ModuleName; use Exporter::VA qw/import AUTOLOAD VERSION/; #### our %EXPORT= ( # all configuration done in this one hash foo => [ v1.0, 'foo_old', v2.0, 'foo_new' ], bar => 'bar_internal', baz => 'baz', fobble => \&figure_it_out, # parameter list is (caller, version, symbol, param-list tail) bobble => \\&_boble_internal, $x => '$x', $y => \\$y, # a hard reference rather than a name :tagname => [ 'foo', 'bar' ], :DEFAULT => [ v1.0, ':_old_imports', v2.3, ':_new_imports' ], :_old_imports => [ 'foo', 'bar', 'baz', 'fobble' ], :_new_imports => [ 'fobble' ], .option => "value", .default_VERSION => v1.5, .warnings => 1 ); #### use ModuleName; #### use ModuleName v2.1; #### use ModuleName v2.1 qw/ foo bar fobble $y/; #### my %Export= ( #... use Exporter::VA (\%Export, 'import'); # look ma, no package globals! #### use Exporter::VA ('import', { foo => \\&internal_foo, bar => \\&internal_bar } ); # put it all inline in this statement. #### %EXPORT= ( &foo => "foo", # & is optional for functions $bar => "$_internal_bar", baz => "" # means "same". ); #### foo => [ v1.0, 'foo_old', v2.0, 'foo_new' ] #### use ModuleName v1.78 ('foo'); # note no comma after v-string #### %EXPORT= ( &foo => \&figure_it_out_later, $bar => sub { ... logic goes here ... }, %fible => sub { \%internal_fible } ); #### sub figure_it_out_later { my ($blessed_export_def, $caller, $version, $symbol, $param_list_tail)= @_; #### %fible => \\%internal_fible #### %EXPORT= ( apple => ... banana => ... pear => ... potato => ... cheeze => ... :fruit => [ qw/apple banana pear/ ] ); #### use ModuleName v1.78 qw/potato :fruit cheeze/; #### %EXPORT= ( :list => [ v1.0, ':_old_list', v2.3, ':_new_list' ], :_old_list => [ 'foo', 'bar', 'baz', 'fobble' ], :_new_new => [ 'fobble' ] ); #### use ModuleName v1.2 ':list'; #### use ModuleName ':_old_list'; #### use ModuleName v2.4 ':list'; #### use ModuleName ':_new_list'; #### %EXPORT= ( foo => [ v1.0, 'foo_old', v2.0, 'foo_new' ], :DEFAULT => [ v1.0, ':_old_imports', v2.3, ':_new_imports' ], :_old_imports => [ 'foo', 'bar', 'baz', 'fobble' ], :_new_imports => [ 'fobble' ], # ... others ... #### %EXPORT= ( -prag => \&callme, # ... #### use ModuleName v1.0 qw/ foo -prag bar/; #### %EXPORT= ( -verbose => sub { my $caller= shift; $verbose{$caller}=1; } #### .allowed_VERSIONS => [ 1.0, # initial relase 1.1, # minor fixes #### %EXPORT= ( .&begin => sub { my ($blessed_export_def, $caller, $version, $symbol, $param_list_tail)= @_; #... #### .default_VERSION => v1.99, # changed stuff with 2.0, must ask for new stuff. #### %EXPORT= ( .plain => [qw/foo $x &zed], #### %EXPORT= ( &foo => "", $x => "", &zed => "", #### %EXPORT= ( .&unknown_import => sub { my ($blessed_export_def, $caller, $version, $symbol, $param_list_tail)= @_; #... #### %EXPORT= ( .&unknown_type => sub { my ($blessed_export_def, $caller, $version, $strange_import_param, $import_list_tail)= @_; #... #### If the import list contains something that is not a scalar, then it is passed to this callback. The thing in question is C<$strange_import_param>. #### .warnings => 0, #### foo => [ v1.0, 'foo_old', v2.0, 'foo_new' ], bar => 'bar_internal', fobble => \&figure_it_out, #### use ModuleName v1.5 qw(foo bar); #### sub import { my $caller= caller; my $export_def= bless find_export_def($caller,\@_), "Exporter::VA"; my $version= get_pending_import_version(); $export_def-> set_client_desired_version ($caller, $version); $export_def -> export ($caller, $version, \@_); } #### package Extend; use Exporter::VA (); @ISA= ('Exporter::VA'); sub resolve { ... # override what I need to change here #### package ModuleName; use Exporter::VA qw/ -derived Extend import AUTOLOAD /; %EXPORT= { ... # # proceed writing my module #### autoload_symbol ($blessed_export_def, $module, $symbol) #### $vstring= client_desired_version ($blessed_export_def, $caller) #### $ref= resolve ($blessed_export_def, $caller, $version, $item) #### package ModuleName; use Exporter::VA qw/-derived ExpEnhancement import AUTOLOAD/;