Re: Error reading delimited list
- From: Kent M Pitman <pitman@xxxxxxxxxxx>
- Date: 15 Mar 2008 03:52:44 -0400
"Steven M. Haflich" <smh@xxxxxxxxxxxx> writes:
It is, I think, a good thing that load lambda binds *package* and
*readtable* so that the values of these variables will not
inadvertently be modified,
As you surely recall, Steve, the X3J13 issue that changed this wasn't
written to keep users from changing it inadvertently, but rather to
allow them to change it advertently. (wow--I looked and that's really
a word.. I never knew.. I had assumed inadvertently had no inverse.)
The difference between these two things is important because it can't
possibly keep you from doing something stupid (such as some of the
things you cite later in your message). All it can do is to allow you
to do something safe in a particular well-known way.
That is, my original proposal (which is why the issue is named as it
is) was to have an IN-SYNTAX macro like IN-PACKAGE), and the group
decided the macro was something a user could write if they wanted, but
that they would bargain down to just having these functions bind the
relevant variables.
but I consider it a botch in the language that we of X3J13 didn't
provide some way to set these variables outside the call to load if
that is indeed what the file really intends to do.
Well, this would beg the question: how far outside. That's like
saying you would like a way to set a special (or even lexical)
variable outside of its scope.
Classically, the way to do either what you propose or the other two
things I suggested, is to make a different side-effect to something
you can change, providing data upward, and then have the caller either
install that data or run some function you've provided. e.g.,
(defvar *foo* 3)
(funcall (let ((*foo* 4)) (lambda () (setq *foo* 5))))
=> 5
*foo*
=> 5
Likewise in LOAD, the usual thing I do in all of my programs that want
to pass environment stuff back is to have the loaded file define some
function, let's call it SETUP-STATE, and then in the loading file do
(SETUP-STATE) after the load if it wants to use that state.
Too many times one wants something like a configuration file to do
this.
I don't discount having wanted to do this, however, at the same time,
I've generally suggested to people that files should NOT actually set
state (other than definitions of functions and variables needed to
make an algorithm work), in order to allow the file to be reloaded
with corrected definitions.
The two-pronged effect of doing a LOAD and then calling a function
often leads to better style in a number of situations, not just
working around this alleged bug. For example, put putting what
amounts to a "script" in a function, it means the function can be
called more than once without the file I/O overhead, and it allows a
proper functional way of providing arguments. A file is a usually
high-overhead way of doing the same.
But if you want that, it's easy enough to define:
(defun eval-file-contents (file)
(with-open-file (stream file)
(loop with eof = (list 'eof)
for form = (read stream nil eof)
while (not (eq form eof))
do (eval form))))
Here is an interesting hack programming challenge, if anyone wants to
attempt a solution:
Despite the lambda binding of *package* and *readtable* by load,
load does not prevent to load-time code from modifying the package
or readtable object that was the value of *package* or *readtable*
when load was called. The challenge is to write a function that can
be called at load time that liberally uses copy-readtable,
rename-package, and the other readtable and package modifying
functions that modify the current readtable or package to be
equivalent to some other desired readtable or package, including in
the package case giving the package the name of the new package.
I see where you're going with this, but I think you're implicitly
advocating a terrible programming style by doing this. I think the
things I've done above are a better way to do that.
Indeed, while it's possible to do even simpler things in loading
files, like have them set the current readtable, I advocate not doing
that. Rather, I think the file should provide a way to either set the
current readtable appropriately (and allow the loader of the file to
call it) or else to have the file define a readtable that someone can
just use, or both (by having the latter readtable be set by the former
function).
I believe both of these functions are computable, but only with
difficulty. They are _not_ semantically transparent, of course,
because functions and variables may have already captured various
package and readtable objects, and the captured objects will not be
eql to the newly modified objects that are the value of *package*
and *readtable*.
Ah good. So you know you're advocating bad style, too, ... and I'm
just saying it explicitly so that people don't let that go quietly
past.
It's good to understand the power at one's fingertips. But the having
of power is not always a call to use it. Just look at the US
presidential administration under Bush and you can see what happens
when people don't understand that.
In fact, people often yield great power to certain others precisely
because they trust that it will not, in general, be used.
Programming is like that, too. Learning programming style is about
which power is ok to use casually and which is not.
.
- References:
- Error reading delimited list
- From: danb
- Re: Error reading delimited list
- From: Pascal Bourguignon
- Re: Error reading delimited list
- From: danb
- Re: Error reading delimited list
- From: Pascal Bourguignon
- Re: Error reading delimited list
- From: danb
- Re: Error reading delimited list
- From: Lars Brinkhoff
- Re: Error reading delimited list
- From: Pascal J. Bourguignon
- Re: Error reading delimited list
- From: Steven M. Haflich
- Error reading delimited list
- Prev by Date: Re: undefined (asdf:system-license on clisp+cywgin
- Next by Date: Re: can someone explain this quote by Tim Daly?
- Previous by thread: Re: Error reading delimited list
- Next by thread: How to make time limited function?
- Index(es):
Relevant Pages
|