Karim Belabas on Sun, 05 Aug 2012 02:41:56 +0200

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

support for packages: require()

Six years ago, Ilya Zakharevich sent a series of short patches to support a new
function require():


inspired by Perl modules. In its simplest form,


it would try to load a GP file exactly once [ the file is not reloaded 
if we require it again ].

More useful:

- require("file.gp", [1,0,4]): do not accept file.gp if its version number 
is less than 1.0.4 [ version 1.0.3 had a bug, say... ]

- file.gp could define functions and variables in a private namespace, say
  modulename::fun1, modulename::fun2, then

    require("file.gp", [1,0,4], ["fun1", "fun2"])

  would import those functions [ or variables ] in the root namespace and
  make them available as fun1(), fun2(), etc. ( via an alias() pointing to
  the private mangled name )


In short, this implements namespaces to protect GP packages from stomping on
each other's variables and functions.

The patch obviously will not apply cleanly in current HEAD, and the
original '::' syntax (borrowed from perl) clashes somewhat with gp2c types.

But it would be easy to reimplement a similar mechanism. What do you think ?



P.S: The full documentation for require() in the patch:

require(modulename,{version}, {features}):
loads the module 'modulename', checks its version against 'version' (unless
'version' is negative---the default), and imports 'features' from the module
(unless 'features' is 0).  The default for 'features' is 1.

A module is a GP file inside a directory on GP load path (or inside a directory
in subdirectory \kbd{lib} of PARI data directory).  Module name should be a
PARI identifier.  If a module name contains \kbd{::}, it is replaced by \kbd{/}
in the corresponding file name.  The file should return a non-zero value. PARI
maintains a list of modules which are already loaded; if 'modulename' is
already loaded, it will not be reloaded.

There are two way for a module to describe its version: either defining a
function modulename::HANDLE_VERSION, or assigning the version to the variable
modulename::VERSION.  In the former case, the argument 'version' becomes the
only argument to this function; the function is assumed to call error() if the
version of the module is not high enough. In the latter case, the value of
argument 'version' is compared with the value of variable modulename::VERSION;
if the versions are of different types, or 'version' is higher, the error
condition is raised.

The module can control export of its features either by defining a function
modulename::HANDLE_EXPORT, or by assigning to variables modulename::EXPORT
and/or modulename::EXPORT_DEFAULT. In the former case the meaning of "export"
is fully controlled by the module itself (unless 'features' is 0); the argument
'features' is passed to this function as is; the second argument given to this
function is an empty string (in future this may be changed to the default
namespace of the caller).

If modulename::HANDLE_EXPORT is not defined, then 'features' should be either 1
(the default), or a list of functions to alias from the namespace modulename::
to the root namespace.  (If the value is 1, it is replaced by the value of
variable modulename::EXPORT_DEFAULT, or modulename::EXPORT if the former is not
defined.)  If variable modulename::EXPORT is defined, the elements of the list
'features' are checked to be contained in the array modulename::EXPORT before
Karim Belabas, IMB (UMR 5251)  Tel: (+33) (0)5 40 00 26 17
Universite Bordeaux 1          Fax: (+33) (0)5 40 00 69 50
351, cours de la Liberation    http://www.math.u-bordeaux1.fr/~belabas/
F-33405 Talence (France)       http://pari.math.u-bordeaux1.fr/  [PARI/GP]