[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [spr5105] changing :element-type of open file stream
[This matter has been assigned the tracking identifier "spr5105".
Please refer to it in any followup communication.]
From: David B. Serafini <serafini@ra-iris.arc.nasa.gov>
1) is there a way to switch the :element-type of an open file stream that has
been read using read-byte? The obvious solution is to do
(file-position)(close)(open)(file-position old-position).
I'd prefer something a little cleaner
No, this isn't possible, at least not without mucking around with lots
of stream internals to which you don't have proper access. For one
thing, a stream usually has a buffer which is a lisp vector of the
same element type, and you would need to replace that, etc. etc.
1b) language question: does setf work on (file-position)? should it?
Despite the obviously-desirable regularity, I am aware of no
indication in CLtL that it should work. The way to set FILE-POSITION
is to use the optional second argument. You could, I suppose, try to
write your own setf method, but even this isn't really legal because
user code is not allowed to install such definitions on symbols in the
COMMON-LISP package.
This irregularity probably comes from ancient back compatibility and
should have been cleaned up by X3J13 -- but it wasn't.
2) My understanding of *default-pathname-defaults* is that it is used both for
opening files and loading files. For real world applications, you often open data
files that should default to the user's local directory, but you load code
files from a system-defined directory. To me, these are fundamentally
different operations, and shouldn't use the same default variable. GNU Emacs
has a variable called load-path, which provides a search list to look for code,
and a different variable (with a different value in each buffer) of the default
path to get data (ie, files to be edited) from. I'd like to implement
something like this, possibly by wrapping a function around load that locally
binds *default-pathname-defaults*. My question is: is this a good idea? is
(load) the right function to change? Will it work for :load and :compile
commands as well?
You definitely don't want to `wrap' anything around any public
function in such a way that changes it's public behavior because you
can't know who else uses the function, and what assumptions are made.
(In other words, you shouldn't advise or otherwise replace the
function definition of LOAD; you can, however, define your own MY-LOAD
that does the binding and then calls LOAD.)
Although *DEFAULT-PATHNAME-DEFAULTS* affects both COMPILE and LOAD, it
does not do so directly. Rather, it affects almost all pathname
operations, thus indirectly affecting OPEN, and in turn, LOAD.
I think you should step back and reconsider the general problem. The
*DEFAULT-PATHNAME-DEFAULTS* mechanism is very simple and designed only
to give the most primitive control of the pathname mapping from a
portable application to an arbitrary local filesystem. A single value
or binding suffices to control the behavior of all the builtin
pathname functions (which include anything that opens a file) only for
the simplest of applicatations -- say, where everything is in a single
directory. You want to make it handle a slightly more complex case,
where two directories are used: code and data. But still other
applications might have still more complicated requirements which your
proposed changes wouldn't handle.
It is necessary to realize, therefore, that nontrivial applications
can't depend on the low-level filesystem `primatives' (such as LOAD
and COMPILE) to support arbitrarily complex interface to families of
component files in a filesystem. Such applications must somehow take
responsibility for computing the pathnames that are passed to the
portable functions such as COMPILE and LOAD. (There is a richer
mechansim as an extension to Allegro -- see the documented variable
SYS:*LOAD-SEARCH-LIST* and the :SEARCH-LIST keyword argument to LOAD.
But this extension isn't portable, nor is it completely general.) In
other words, the appropriate design might be for you to implement some
higher-level functional layer which manages your interface to the
files you `open' and `load' for various high level purposes, rather
than calling OPEN, LOAD, and COMPILE directly. If you think about it,
this is exactly what the various available DEFSYSTEM utilities do for
you (including the early one in Allegro 3.1 and 4.0, and the more
sophisticated one in 4.1). They are a sublanguage for the
specification of operations on files. Usually the operations are the
usual compiling and loading of normal code modules, but the DEFSYSTEM
sublanguage can also easily support other processing, such as the
analysis and processing of families of telemetry data files, or
whatever. The knowledge how to do so is a part of your application --
in the general case it can't properly reside in a single
general-purpose variable such as *DEFAULT-PATHNAME-DEFAULTS*.