gumby@Cygnus.COM (David Vinayak Wallace) (09/23/90)
Date: 21 Sep 90 22:09:56 GMT From: miller@GEM.cam.nist.gov (Bruce R. Miller) Larry Masinter wrote: >[As a side note, many learning LISP programmers frequently do > encounter self-modifying code and are mystified by it, e.g., > (let ((var '(a b c))) > ... > (nconc var value)) Without digging thru CLtL to determine its legality, it seems pretty clear that it is unclear what it SHOULD do! And that different interpreters/compilers will make different choices. And that the Committee probably didn't even want to specify. In any case, one could imagine a perfectly legitimate interpretter consing the list fresh every time, giving a 3rd behavior. Before you groan, consider that this might in fact be the most consistent behavior! The (QUOTE (A B C)) form is (conceptually, at least) evaluated each time the function is called! Should (QUOTE (A B C)) sometimes return (A B C FOO)? The interpretation of either case is straightforward. Quote returns the object it was handed. It doesn't try to guess "what you meant." After all, the code isn't text; quote just has a pointer to the car of the list you handed it! I would be unhappy if quote performed computation each time you used it! A very common idiom is to pass a quoted, uninterned symbol around as a marker in some structure. (I used to use '(())). This is the only way I can get a token I guarantee won't appear in my input stream! Anyway, the capability to side-effect constants in storage was not removed for taste reasons, but efficiency; it permits me as a lisp implementor to place code into read-only storage (and possibly share it among processes).
miller@cam.nist.gov (Bruce R. Miller) (09/25/90)
In article <GUMBY.90Sep22150717@Cygnus.COM>, David Vinayak Wallace writes: > Date: 21 Sep 90 22:09:56 GMT > From: miller@GEM.cam.nist.gov (Bruce R. Miller) > Larry Masinter wrote: > > (let ((var '(a b c))) > > ... > > (nconc var value)) > ... > In any case, one could imagine a perfectly legitimate interpretter > consing the list fresh every time, giving a 3rd behavior. Before you > groan, consider that this might in fact be the most consistent behavior! > The (QUOTE (A B C)) form is (conceptually, at least) evaluated each time > the function is called! Should (QUOTE (A B C)) sometimes > return (A B C FOO)? > > The interpretation of either case is straightforward. > > Quote returns the object it was handed. It doesn't try to guess "what > you meant." After all, the code isn't text; quote just has a pointer > to the car of the list you handed it! > I'm a little confused about what you're saying. In the simplest case, READ consed up the list, and QUOTE just returns its arg. Clearly if you repeatedly INTERPRETED the above form, you get the same result each time. (but perhaps not within a defun which may or may not digest the form!) Compilation makes it a bit less clear; READ is no longer involved. What pointer are we handing it? If you WANT the permanent change then you should presumably write (let ((var '(a b c))) (defun foo (..) .. (nconc var value))) to make clear the extent of var. > I would be unhappy if quote performed computation each time you used > it! A very common idiom is to pass a quoted, uninterned symbol around > as a marker in some structure. (I used to use '(())). This is the > only way I can get a token I guarantee won't appear in my input > stream! > So would I!!!! I dont quite follow your example, but I'm certainly not suggesting that quote should creates a new list -- nor even that the (a b c) should be consed anew each time. Indeed, I expect the quote should `disappear' upon compilation. I just wanted to say that the EFFECT of that approach MAY be the most appropriate behavior. > Anyway, the capability to side-effect constants in storage was not > removed for taste reasons, but efficiency; it permits me as a lisp > implementor to place code into read-only storage (and possibly share > it among processes). Ah, if it's in read-only storage then you can NOT modify it, no? BTW; Tim Moore, in another posting pointed out that this is considered `illegal' although he didn't say if CLtL specified whether an error is signalled or whether it is simply `undefined'. bruce
moore%cdr.utah.edu@cs.utah.edu (Tim Moore) (09/25/90)
In article <2863191137@ARTEMIS.cam.nist.gov> miller@cam.nist.gov (Bruce R. Miller) writes: > >In article <GUMBY.90Sep22150717@Cygnus.COM>, David Vinayak Wallace writes: >> Date: 21 Sep 90 22:09:56 GMT >> From: miller@GEM.cam.nist.gov (Bruce R. Miller) >> Larry Masinter wrote: >> > (let ((var '(a b c))) >> > ... >> > (nconc var value)) >> ... >> Quote returns the object it was handed. It doesn't try to guess "what >> you meant." After all, the code isn't text; quote just has a pointer >> to the car of the list you handed it! >> >I'm a little confused about what you're saying. In the simplest case, >READ consed up the list, and QUOTE just returns its arg. >Clearly if you repeatedly INTERPRETED the above form, you get the same >result each time. (but perhaps not within a defun which may or may >not digest the form!) Regardless of any processing done by defun, the form is read only once. It is true that the cons cell that is the value of var is the same from invocation to invocation. However, the intention is that the last element of the list whose head is that cons cell will be changed each time through the code. So the result, (say, the return value of nconc) is different each time. >If you WANT the permanent change then you should presumably write >(let ((var '(a b c))) > (defun foo (..) > .. (nconc var value))) >to make clear the extent of var. This implies that foo is a closure. The previous code is an idiom that dates from Lisps without closures. You're still trying to modify a quoted constant here. If you have closures you might as well do (let ((var '(c b a))) (defun foo (...) (push value var))) >> Anyway, the capability to side-effect constants in storage was not >> removed for taste reasons, but efficiency; it permits me as a lisp >> implementor to place code into read-only storage (and possibly share >> it among processes). > >Ah, if it's in read-only storage then you can NOT modify it, no? If you want to modify it, don't quote it. > >BTW; Tim Moore, in another posting pointed out that this is considered >`illegal' although he didn't say if CLtL specified whether an error is >signalled or whether it is simply `undefined'. In the terminology of CLtL, "it is an error". This means that valid Common Lisp programs can't do it, but if it's done the results are undefined and an error need not be signalled. > >bruce Tim Moore moore@cs.utah.edu {bellcore,hplabs}!utah-cs!moore "Ah, youth. Ah, statute of limitations." -John Waters
jeff@aiai.ed.ac.uk (Jeff Dalton) (09/26/90)
I couldn't quite make out who wrote the stuff quoted below, so I decided to avoid the risk of misattribution by not attributing it to anyone. >> I would be unhappy if quote performed computation each time you used >> it! A very common idiom is to pass a quoted, uninterned symbol around >> as a marker in some structure. (I used to use '(())). This is the >> only way I can get a token I guarantee won't appear in my input >> stream! I always call LIST or CONS to get a unique object, rather than rely on anything that involves QUOTE, although some people have pointed out that, if you want an object that cannot appear in a stream, the stream itself will do (unless, thanks to #., the stream is held in a global variable). That is, you do something like: (with-open-stream (s ...) (do ((input (read s nil s) (read s nil s))) ((eq input s)) (process input))) -- Jeff
masinter@parc.xerox.com (Larry Masinter) (10/04/90)
Many quotes ago I wrote something about: >> > (let ((var '(a b c))) >> > ... >> > (nconc var value)) >> ... This certainly isn't legal Common Lisp, and I didn't mean to imply that it is. What I was trying to say was just that every Lisp programmer will eventually stumble on a *bug* of this form and be baffled by it. If you wanted to do something like this actually you'd write (defvar *values* (list 'a 'b 'c)) and then nconc *values* away. Somebody else wrote: >If you WANT the permanent change then you should presumably write >(let ((var '(a b c))) > (defun foo (..) > .. (nconc var value))) >to make clear the extent of var. This is also illegal. I think in X3J13 we struggled a lot with the wording to try to rule out the 'obvious' illegal situations. It was hard. Gumby (I think) wrote: >> Anyway, the capability to side-effect constants in storage was not >> removed for taste reasons, but efficiency; it permits me as a lisp >> implementor to place code into read-only storage (and possibly share >> it among processes). I personally didn't think the issue was either taste or efficiency. In general, I never saw that X3J13 declaring something "is an error" in Common Lisp as an act of "removing" a capability, but rather of just documenting a way in which program behavior was bound to be unpredictable. I think the main problem is that you cannot even talk about the semantics of code that modifies itself or its lexical constants using the language in which Common Lisp is described. It would be unreasonable to require implementations to *signal* an error when constants were modified because it would *require* all implementations to store such constants in read-only storage and trap attempts to modify them. In some posting, Gumby said: >I would be unhappy if quote performed computation each time you used >it! A very common idiom is to pass a quoted, uninterned symbol around >as a marker in some structure. (I used to use '(())). This is the >only way I can get a token I guarantee won't appear in my input >stream! You have to be very careful here. I remember the debate, but not the resolution, but I believe, is that it is possible that a compiler (or interpreter or whatever makes your Common Lisp run) may also collapse EQUAL, quoted structures, e.g., (let ((x '(())) (y '(()))) (eq x y)) might be true, and, furthermore, the '(()) might even be collapsed with some other unrelated lexical occurrence of a quoted structure. (E.g., one used by READ). Thus, if you want a token that will not occur in your input stream, you should probably do: (defconst *end-of-stream* (list nil)) and then use *end-of-stream* wherever you want a marker. I think this is better style, in any case, and hardly less efficient. -- Larry Masinter (masinter@parc.xerox.com) Xerox Palo Alto Research Center (PARC) 3333 Coyote Hill Road; Palo Alto, CA USA 94304 Fax: (415) 494-4333