From jmc at research.bell-labs.com  Fri Sep  5 13:12:06 2003
From: jmc at research.bell-labs.com (John Chambers)
Date: Fri Sep  5 18:13:40 2003
Subject: [Rd] namespaces and S4 methods/classes
Message-ID: <3F58B5D6.23D704B@research.bell-labs.com>

The current version of the methods package now has a namespace. Packages
using S4 methods and classes can have NAMESPACE files.  New directives
can be included in NAMESPACE files to import and export classes and
methods.

Namespaces allow cleaner definition of the API for packages, and are
needed for future improvements to R.

NOTE: This is a major revision.  In principle, it should be back
compatible, and it passes the checks (on linux).  But approach with
caution, namespaces do change the language semantics, and we will likely
encounter some surprises.

The new directives, in addition to those described in Luke Tierney's
article in the June, 2003 R News, are:

exportClasses(...)
exportMethods(...)

importClassesFrom(package, ...)
importMethodsFrom(package, ...)

The `...' arguments are the names of classes or of generic functions
as appropriate.  The exportClasses and exportMethods directives export
the corresponding class definitions and all the methods for the
functions.  Similarly, the importClassesFrom and importMethodsFrom
import the class definitions and all the methods defined for the
functions.

This is a preliminary version, with several known deficiencies.  Here
are some points to note.

1.  Currently, NAMESPACE files  using methods must explicitly import
    the methods package, via the `import(methods)' directive.

2.  Private (i.e., non-exported) methods for primitive functions don't
    currently really work.  They don't appear explicitly, but are
    defined internally.  (This will be fixed, but needs a change in
    the way methods are dispatched for primitives.)

3.  Methods are exported all-or-nothing; it is not possible to export
    some of the methods for a function.  (Again, this will require a
    different mechanism than is currently used.)

    A related point is that the exported methods are only the methods
    defined in this package, not methods imported for the same
    function.  (As a result, it may still be necessary to require() a
    package even if there is an import() directive for it, so users
    will see all the methods.  This will probably change.)

4.  The NAMESPACE mechanism should work with or without a saved image
    from the INSTALL, but there may be subtleties not uncovered.  (As
    always with classes and methods, there is an efficiency advantage
    to using saved images.)

5.  The exported names from the methods package are quite liberal, but
    there may be some currently used functions that come up missing; let
    us know.  In the future the exports from the methods package will
    probably shrink, to make the API cleaner.

6.  An important change required by namespaces is that classes be
    directly identifiable as objects, not just the class name as a
    string.  The current version takes a first step by including the
    package name as an attribute in the class() value for objects with
    formal classes.  A better mechanism may be used later.

7.  There are some problems with debugging using namespaces.  At the
    moment, the trace() function has been instrumented to override
    locked bindings, but we don't guarantee this in the future.
    (However, some mechanism will be needed--it certainly was in
    debugging the changes so far.)

8.  In case of serious problems, you should be able to go back to a
    non-namespace version of the methods package by moving the
    NAMESPACE file in $R_HOME/src/library/methods, removing all.R and
    running make.  (At least, it works here.)


Here are examples of two package NAMESPACE files:  withNamespace and
withNamespace2, the latter using the former:

withNamespace/NAMESPACE:

import(methods)
export(f1, ng1)
exportMethods("[", initialize)
exportClasses(c1)

-----------------------
withNamespace2/NAMESPACE:

import(methods)
importFrom(withNamespace, ng1)
importClassesFrom(withNamespace, c1)
importMethodsFrom(withNamespace, f1, "[")
export(f4, f5, f1)
exportMethods(f6, "[", f1)
exportClasses(c1, c2)


-- 
John M. Chambers                  jmc@bell-labs.com
Bell Labs, Lucent Technologies    office: (908)582-2681
700 Mountain Avenue, Room 2C-282  fax:    (908)582-3340
Murray Hill, NJ  07974            web: http://www.cs.bell-labs.com/~jmc


[Rd] namespaces and S4 methods/classes
John Chambers