From: Richard Klinda
Subject: misunderstanding with plists
Date: 
Message-ID: <87pubevuwl.fsf@writeme.com>
Hoi All!

(I'm not a native English speaker so please try to overlook my
grammatical mistakes, thank you.)

I'm trying to write a program for myself to solve the following problem:
at the university in the next semester I want to pick 8 classes.  Every
class has 2-3 appointment time and it's the students' "mission" to
choose the right combination, with which there are no time collisions.

My program is complete (sic), it consists of two (defun ..)s, but one of
the defuns has a characteristic that I don't understand (Fufie and Dash
were kind and tried to enlighten me on irc/#lisp but I still don't
*understand* why this strange thing happens.)

The code (truncated, but works as it stands):

(defun score-it! (way)
  (let ((subject nil)
>        (result '(monday nil tuesday nil wednesday nil thursday nil friday nil)))
>    (print (list 'first-score-it\: result))
    (dolist (item way)
      (cond ((symbolp item) (setf subject item))
            (t (let ((day (first item))
                     (start (second item))
                     (end (third item)))
                 (dotimes (index (- end start) result)
                   (if (member (+ start index) (getf result day))
                       (setf (getf (getf result day) (+ start index))
                             (append (list (getf (getf result day) (+ start index)))
                                     (list subject)))
                     (setf (getf result day)
                           (append (getf result day)
                                   (list (+ start index))
                                   (list subject)))))))))))

(I marked the interesting lines with >s.)

First run gives the result:

,----
| * (score-it! '(math (monday 8 10) (tuesday 8 10) electronics (monday 8 10)))
| (|FIRST-SCORE-IT:|
|  (MONDAY NIL TUESDAY NIL WEDNESDAY NIL THURSDAY NIL FRIDAY NIL)) 
| NIL
`----

So result has the value I assigned to it via (let ...

Second run:

,----
| * (score-it! '(math (monday 8 10) (tuesday 8 10) electronics (monday 8 10)))
| (|FIRST-SCORE-IT:|
|  (MONDAY (8 (MATH ELECTRONICS) 9 (MATH ELECTRONICS)) TUESDAY (8 MATH 9 MATH)
|   WEDNESDAY NIL THURSDAY NIL FRIDAY NIL)) 
| NIL
`----

Woops, clearly (let ((result '(monday nil ..))) doesn't assign the value
to result, result seems to remember its previous value.

I *really* don't understand what's going on.  Fufie and Dash talked
about something that I shouldn't use property lists but I must have a
basic misunderstanding with it because I don't understand how the use of
getf does this effect, and this is my main question, why is that?

My line of thinking: when (let ((result '(...))) .....) <- ends, the
variable 'result' should become destroyed / forgotten / whatever, so at
the next run of 'score-it!', 'score-it!' should work with a brand new
symbol 'result' without any references to the previous 'result'.

(I have the following books, you can use them as a reference if it's
more comfortable for you: CLtL, Koschmann: The Common Lisp Companion,
Franz: Common Lisp The Reference.)

Thanks in advance for your answers.

-- 
ignotus
                          Emacs: the answer to the world surplus of CPU cycles.

From: Barry Margolin
Subject: Re: misunderstanding with plists
Date: 
Message-ID: <%Cm17.88$on2.1869@burlma1-snr2>
In article <··············@writeme.com>,
Richard Klinda  <·······@writeme.com> wrote:
>Woops, clearly (let ((result '(monday nil ..))) doesn't assign the value
>to result, result seems to remember its previous value.

The problem is that you're modifying a literal, which is modifying the
program itself.  Use:

(let ((result (list 'monday nil 'tuesday nil 'wednesday nil ...)))
 ...)

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kent M Pitman
Subject: Re: misunderstanding with plists
Date: 
Message-ID: <sfwk81mdkoh.fsf@world.std.com>
Richard Klinda <·······@writeme.com> writes:

> (defun score-it! (way)
>   (let ((subject nil)
> >        (result '(monday nil tuesday nil wednesday nil thursday nil friday nil)))
> >    (print (list 'first-score-it\: result))
>     (dolist (item way)
>       (cond ((symbolp item) (setf subject item))
>             (t (let ((day (first item))
>                      (start (second item))
>                      (end (third item)))
>                  (dotimes (index (- end start) result)
>                    (if (member (+ start index) (getf result day))
>                        (setf (getf (getf result day) (+ start index))
>                              (append (list (getf (getf result day) (+ start index)))
>                                      (list subject)))
>                      (setf (getf result day)
>                            (append (getf result day)
>                                    (list (+ start index))
>                                    (list subject)))))))))))
> 
> (I marked the interesting lines with >s.)
> 
> First run gives the result:
> 
> ,----
> | * (score-it! '(math (monday 8 10) (tuesday 8 10) electronics (monday 8 10)))
> | (|FIRST-SCORE-IT:|
> |  (MONDAY NIL TUESDAY NIL WEDNESDAY NIL THURSDAY NIL FRIDAY NIL)) 
> | NIL
> `----
> 
> So result has the value I assigned to it via (let ...
> 
> Second run:
> 
> ,----
> | * (score-it! '(math (monday 8 10) (tuesday 8 10) electronics (monday 8 10)))
> | (|FIRST-SCORE-IT:|
> |  (MONDAY (8 (MATH ELECTRONICS) 9 (MATH ELECTRONICS)) TUESDAY (8 MATH 9 MATH)
> |   WEDNESDAY NIL THURSDAY NIL FRIDAY NIL)) 
> | NIL
> `----
> 
> Woops, clearly (let ((result '(monday nil ..))) doesn't assign the value
> to result, result seems to remember its previous value.

Hint: NEVER modify a quoted constant.  When you do, you're risking
modifying the data area of the stored program itself, as probably
happened here.

I suggest: 
 (let ((result (copylist '(monday nil tuesday nil ...)))) ...)
or
 (let ((result (list 'monday nil 'tuesday nil ...)))
so that you're sure you're working with fresh structure and not bashing
structure that belongs to something else.

The problem is actually worse than you fear because the compiler is permitted
to share quoted structure with other functions, so another function that
used the identical list '(monday nil tuesday nil ...) could also be getting
trashed by your unwarranted side-effect.

It may help to remember that Lisp code source is not the text you typed
but the expression structure.

> I *really* don't understand what's going on.  Fufie and Dash talked
> about something that I shouldn't use property lists but I must have a
> basic misunderstanding with it because I don't understand how the use of
> getf does this effect, and this is my main question, why is that?
> 
> My line of thinking: when (let ((result '(...))) .....) <- ends, the
> variable 'result' should become destroyed / forgotten / whatever, so at
> the next run of 'score-it!'

The variable is destroyed, but the object which will be used to initialize
it if the program is run again is not.

In Lisp, objects have lifetimes independent of variables they live in.
This is called "first-class data".  Variables are just places to put
things, they are not the things themselves.