[comp.lang.lisp] What replaces REQUIRE

maverick@fir.Berkeley.EDU (Vance Maverick) (02/08/91)

It seems that ANSI is just dropping the module feature.  Apparently we
are all to roll our own.  I quote: "XJ13 commented that the file-loading
feature of REQUIRE is not portable, and that the remaining functionality
is easily implemented by user code."  (CLtLII p.277)  This is true but a
little unfriendly, and invites portability problems.

	Vance

pierson@encore.com (Dan L. Pierson) (02/13/91)

In article <10901@pasteur.Berkeley.EDU> maverick@fir.Berkeley.EDU (Vance Maverick) writes:
   It seems that ANSI is just dropping the module feature.  Apparently we
   are all to roll our own.  I quote: "XJ13 commented that the file-loading
   feature of REQUIRE is not portable, and that the remaining functionality
   is easily implemented by user code."  (CLtLII p.277)  This is true but a
   little unfriendly, and invites portability problems.

The problem is that including REQUIRE *in the standard* enforces
portability problems.  The argument goes like this:

1. The file loading feature of REQUIRE is speced to be non-portable,
   "If the pathname argument is nil or is not provided, the sytem will
   attempt to determine, in some system-dependent manner, which files
   to load."

2. Some current implementations such as TI Explorer and Coral Common
   Lisp (now Allegro Common Lisp for the Mac or some such), include
   and depend heavily on powerful, useful, very system-dependent
   implementations of the above.  For example:
   in Coral (require 'quickdraw) is the standard way to access the
   Mac-specific graphics extensions.

3. A proposal to delete the second argument of REQUIRE and restrict it
   to just the portable functionality was very strongly resisted by
   the implementors who would be hurt by it.

4. (here is where it gets tricky) Standardizing REQUIRE including the
   non-portable parts is a portability trap.  Let's say you're
   developing what you fondly think will be a large portable
   application on an Explorer.  Since REQUIRE is portable, you use it
   in lots of places to ensure that your inter-module dependencies are
   satisfied.  It works just fine; everything you need is always
   correctly loaded.  Now you move your finished application to a
   major stock-hardware Common Lisp (or worse, give it to someone else
   to move).  Everything breaks with a complex, undoumented network of
   unsatisfied dependencies because REQUIRE on the Explorer not only
   check to see if dependencies were satisfied, it fixed them up with
   system-dependent magic.  This is not a bad feature, but it *is* a
   non-portable one.  What fooled you was the official lie that
   REQUIRE was a portable function that you could safely use in
   portable code.

5. (the important part) Removing REQUIRE from the standard does not
   mean that implementors must, or even should, remove it from their
   implementations.  It merely means that it should be described as
   what it is: an implementation dependent extension.  (The standard
   does require that such symbols live in a package other than
   COMMON-LISP.  However, USER can use system-dependent packages so
   authors of non-portable code shouldn't have to notice any change.)
--

                                            dan

In real life: Dan Pierson, Encore Computer Corporation, Research
UUCP: {talcott,linus,necis,decvax}!encore!pierson
Internet: pierson@encore.com

jeff@aiai.ed.ac.uk (Jeff Dalton) (02/15/91)

In article <PIERSON.91Feb13104336@xenna.encore.com> pierson@encore.com (Dan L. Pierson) writes:
>In article <10901@pasteur.Berkeley.EDU> maverick@fir.Berkeley.EDU (Vance Maverick) writes:
>   It seems that ANSI is just dropping the module feature.  Apparently we
>   are all to roll our own.  I quote: "XJ13 commented that the file-loading
>   feature of REQUIRE is not portable, and that the remaining functionality
>   is easily implemented by user code."  (CLtLII p.277)  This is true but a
>   little unfriendly, and invites portability problems.
>
>The problem is that including REQUIRE *in the standard* enforces
>portability problems.  The argument goes like this:
>
>1. The file loading feature of REQUIRE is speced to be non-portable,
>   "If the pathname argument is nil or is not provided, the sytem will
>   attempt to determine, in some system-dependent manner, which files
>   to load."

[And then: some systems actually do determine which files to load in
an interesting way.  Some programmers might think that, because
REQUIRE is part of standard CL, this interesting behavior is standard
too.  But it isn't.  A proposal to make REQUIRE portable and thus rule
out the interesting behavior provided by some systems was resisted.
So it was decided to not make anything about REQUIRE standard and let
implementations do whatever they wanted (as an extension to std CL).]

I think this is the best explanation posted so far (thanks Dan!),
and this is not the first time the issue has come up.

On the whole, I think it probably _is_ better to take REQUIRE out
of standard CL.  It was confusing to call what PROVIDE and REQUIRE
did "modules" (given what module means in languages that "have
modules", such as Modula-II), and it was far from clear that
PROVIDE and REQUIRE would fit into any good, portable system
defining and building tools that were eventually developed.

It used to be possible to write large-ish Franz Lisp programs using
something sort of like REQUIRE (called "environment") together with a
Makefile (Franz is Unix after all).  In Common Lisp I eventually gave
up and wrote a simple DEFSYSTEM.  Still, I think REQUIRE could be used
in that way, and the basic functionality of being able to tell if
something has already been loaded is so generally useful that I think
it's a shame not to have some standard way to do it.

Moreover, it _is_ possible to use REQUIRE portable, or at least
that's my interpretation of CLtL (and that of some other people
who have posted in the past).  In CLtL II, page 278, we find:

   The _pathname_ argument, if present, is a pathname or a list of
   pathnames whose files are to be loaded in order, left to right.
   If the _pathname_ argument is NIL or not provided, the system
   will attempt to determine, in some system-dependent manner,
   which files to load.

I take it that this implies that if the _pathname_ argument is
provided and is not NIL, then the system will load the specified
file(s) and NOT attempt to determine, in some system-dependent
manner, which files to load.  I realize that it's possible to 
argue that when something says "If X then Y.  If not X then Z"
that this doesn't strictly imply that if X, then Z won't be
done; but I think such a reading would be a little perverse.

We could go on to say that _pathnames_ aren't portable, but I
don't think that's very convincing.

So, I think it's understandable that some people would think X3J13's
decision to de-standardize REQUIRE was a bit arbitrary and against
the interests of users.  I think it's understandable but, as I said,
on balance I think the decision was correct.  All that's lacking is
a complete explanation, which I think we now almost have.

-- Jeff