[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Here's my two cents worth on the code portability issue. I think I've
probably had as much experience with writing portable Lisp code as anyone
here, being one of the chief PCLS architects (currently running under Unix
and VMS), and having written a large amount of application code which has
been ported to other CL implementations.
I'm probably going to get flamed for this, but in my view, the name of the
package containing local extensions, or exactly what symbols live in the
Lisp package, are fairly trivial issues. My experience has been that, if
you want your code to be portable, you have to put a lot of effort into
making it that way from the beginning, and there are many problems more
troublesome than obscure package manipulations that you have to overcome
in the process. Here's a few of the issues that come to mind:
1. You can't count on being able to directly manipulate pathname
components. Explicit namestrings generally lose too.
2. There is no agreement on what *features* should contain, or what
package the symbols live in. Hence, you can't really depend on #+ and #-
to do anything useful.
3. Loading files can really be a nuisance, particularly if you want to
be able to look for them in more than one place, or if you want to look
for them somewhere other than the default directory. "Require" can be made
to do the right thing in some implementations but not others. "Load" is
OK if you can somehow get a pathname built. (I don't really have a good
solution for this problem; in PCLS we use a few global variables to hold
the names of various system-dependent files and where to look for them.)
4. It's amazing how certain implementations that don't admit to being
subsets are missing huge amounts of functionality.
5. Handling for streams regarding prompting, buffering, terminal
interrupts, etc. varies widely between implementations, depending on what
the primitives offered by the operating system are. (The VMS and Unix
versions of PCLS don't even behave the same in this respect.)
6. Lack of a portable error-handling mechanism makes it tough to do
stand-alone applications that will be used by non-Lisp wizards. (Popping
into the debugger is fine for developers, but doesn't do much for random
users who think that Lisp is what they speak in San Francisco....)
Hopefully this will change in the near future.
7. There is no standardized model about what kinds of processing happens
at compile time, particularly regarding defining forms such as deftype and
defstruct, or perverse manipulations of the package system (setq'ing
*package* directly?) Code that works fine interpretively often fails to
My general approach to portability is to avoid the use of implementation-
specific or poorly standardized features where possible, and where I must
refer to them, put all the references in a separate file and wrap an
interface function around them. It makes it a lot easier when everything
you need to tweak to get the code to run under a different implementation
is all in one place instead of scattered randomly through two dozen files.