Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!samsung!think!ames!zodiac!rshu From: rshu@zodiac.ADS.COM (Richard Shu) Newsgroups: comp.lang.lisp Subject: Re: NCONC & Functions Message-ID: <9893@zodiac.ADS.COM> Date: 29 Nov 89 00:35:54 GMT References: <464@ntcsd1.UUCP> Sender: news@zodiac.ADS.COM Reply-To: rshu@ads.com (Richard Shu) Distribution: na Organization: Advanced Decision Systems, Mt. View, CA (415) 960-7300 Lines: 68 In article <464@ntcsd1.UUCP> mps@ntcsd1.UUCP (Michael Smith) writes: > >On both a TI and a Sun (using Sun Common Lisp (lucid)), the following occurs: > > >(DEFUN foo1 () '(a b c)) > >FOO1 > >(foo1) > >(A B C) > >(NCONC (foo1) '(d e f)) > >(A B C D E F) > >(foo1) > >(A B C D E F) > >(DEFUN foo2 () (LIST 'a 'b 'c)) is unaffected in the same situation. Same thing happens on a Symbolics running Genera 7.2 >I think I understand what is happening. NCONC is treating the pointer re- >turned by evaluating (FOO1) just as if it were evaluating a variable FOO1. >But I don't like it. There is no variable FOO1, and NCONC is in effect re- >defining the function FOO1. I'm not an expert at Common Lisp or its implementation but I think your explanation is a little off base. The point is that '(a b c) is a constant and the compiler/interpreter is deciding to treat it that way. Thus, every call of FOO1 returns the SAME copy of '(a b c). This can be shown by evaluating (eq (FOO1) (FOO1)) and seeing that the value returned is T. For comparison (eq (FOO2) (FOO2)) returns NIL. All this is a little weird since (eq '(a b c) '(a b c)) also returns NIL. I understand your confusion but I'll bet somebody can give the "official" explanation why Common Lisp works this way. >I have been using the rule: don't use destructive operations on data struc- >tures you care about. Now this turns out to be insufficient. Actually, the rule is don't use destructive operations on data structures if there might be another pointer (direct or indirect) to the same object and that pointer should not reflect the change that a destructive operation would make. Using this rule requires real thought about the life history of the data structure you're about to change destructively. You have to consider every function that had a chance to reference the data structure since it was created (which means you have to know when it was created). This can be a real pain if data structure's life history is not readily apparent. As a result, I only use destructive operations when the life history is obvious. Typically, I do stuff like (setf (cdr x) y) where x is a cons cell of an alist that is not part of any other alist. You can see why the simplified version of this rule translates to: Don't use destructive operations at all. >Is there a >rule regarding when destructive operations can affect the values returned >by functions they are not part of? I guess there's a corollary that says: make sure you create new copies of lists if that's what you want. Don't use QUOTE (') to cons up data structures. If you don't like LIST, use the BACKQUOTE macro (`). I've been shafted by variations of your bug where the problem was using QUOTE instead of BACKQUOTE. Rich (responsible-p ADS message) NIL (si:halt)