Comments are solicited at this point in the design. It may be a couple weeks before I proceed with an implementation.

In discussing versioning exports, I realized that the fundimental feature lacking in Exporter is the ability to have the internal and exported name differ. That is, an alias ability.

Versioning then is an application of using different aliases for different versions.

So I'm tennitivly calling this module Exporter::VA, for Version and Alias abilities.

Here is the user interface; that is, how a module author takes advantage of these features.

There are several kinds of information: as with the traditional system, there are symbols that are allowed to export, a subset of those that are default, and tags for named sets of symbols.

I want to have aliases that differ by version, as well as the (hopefully common) case of changing which symbols are exported by default based on version.

To that end, I've combined all the information into one hash. Here is an example:

use Exporter::VA; %EXPORT= ( foo => [ v1.0, 'foo_old', v2.0, 'foo_new' ], bar => 'bar_internal', baz => 'baz', fobble => \&figure_it_out, # parameter list is (caller, version, sy +mbol, param-list tail) $x => '$x', :tagname => [ 'foo', 'bar' ], :DEFAULT => [ v1.0, ':_old_imports', v2.3, ':_new_imports' ], :_old_imports => [ 'foo', 'bar', 'baz', 'fobble' ], :_new_imports => [ 'fobble' ] ); Exporter::VA::plain qw/ baz $x /;
The %EXPORT package variable is a set of hash pairs. If the key begins with a : then it is a "tag", described below. If it is an identifier name or begins with a sigel, it is a symbol name.

Symbol Entries

A symbol name (in the key or value) may omit the & for functions.

The value may be the name of the internal symbol; a code reference; or an array ref.

If simply a string, it is the name by which the symbol is defined within the module. foo => 'foo_x' means to take the package's &foo_x and make it known as &foo in the caller's namespace. If the value name is equal to the key name, then no renaming is done (see Exporter::VA::plain below).

If the value is a list, the list alternates v-strings and symbol names. The symbol name will be taken when it appears between two v-strings such that the desired version is >= to the left and < the right.

If the value is a code ref, then it is called to figure it out at run time. It must return a reference to the proper type of thing, and that will be entered into the caller's namespace. It is called with the caller's package name, desired version v-string, the symbol name, and a reference to the rest of the import parameter list. The last allows the callback to pull more arguments (and delete them), or otherwise modify the remainder of the list.

Tag Enteries

A key that begins with a : character is a tag, and they work like the traditional feature. If you import a tag name, it is expanded into the list of names automatically.

The value is a list of names (symbol names and other tag names are allowed) or a list of alternating v-strings and tag names.

If a list of names, the list replaces the tag in the import parameter list and processing continues with the expanded content so nested tag lists are handled.

If a list of alternating v-strings and tag names, the logic is like that for symbol names. The tag is replaced by the other tag based on the desired version, and processing continues with that tag.

The :DEFAULT tag is used if an empty argument list is imported. It is just like any other tag, just taken as a default.

they work together

If a package imports the default in the above example, it will note that foo was imported in versions before v2.3 but dropped as a default in that version. But, in version 2.0 the implementation changed, so it will pull in foo_old if the requested version is less than 2, or foo_new if between 2.0 and 2.3, or not import it at all if 2.3 or later.

plain

Not every symbol has a version decision or alias. Degenerate cases such as  baz => 'baz', $x => '$x' are a bore.

So, the function call Exporter::VA::plain qw/ baz $x /; will populate these simple entries. Each argument to plain is added as an entry to %EXPORT whose value is the same as the tag.

Aliases and Non-imported calls

An alias only works if imported! If Module::foo was called directly, it would indeed try and call a function named foo, not foo_old or foo_new.

This thing only imports. This issue is different, but this thing will help a little.

If you indeed write a sub named foo, it could check the caller and decide at run time what to do based on which version the caller asked for.

To this end, the package variable %EXPORT_CALLERS associates importers with v-strings as supplied in their use statement.

The function Exporter::VA::resolve (symbol, optional-vstring) may also be used to traverse the %EXPORT data for you. If the v-string is omitted, it is looked up based on the caller's package.

default version

The package global $EXPORT_DEFAULT_VERSION may be defined. If so, it is taken as the version if no v-string is given in the use statement. Otherwise, a v-string is required in the use statement.


In reply to Module Design strawman - Exporter::VA by John M. Dlugosz

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.