From: Peter Buchlovsky
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <87bsa46ra9.fsf@cs.bham.ac.uk>
"Donovan Parks" <······@uvic.ca> writes:

> Hello,
> 
> I have a list of list in the following format:
>     L = ((0 0 0 0) (0 0 0 0) (0 0 0 0))
> 
> Now, I need to be able to change an arbitrary atom.  For example, I
> would like to modify the list so that is becomes:
>     L' = ((0 X 0 0) (0 0 0 0) (0 0 0 0))
> 
> I thought I could do this using setf as follows:
>     (setf (nth 2 (nth 1 L) 'X))

There is another reason why the above won't work. In the outer call to
NTH you pass it three arguments even though it only expects two. From
now on I'll assume that you intended to write:

(setf (nth 2 (nth 1 L)) 'X)

> Unfortunately, this results in:
>     L' = ((0 X 0 0) (0 X 0 0) (0 X 0 0))

How do you create L? If, as I suspect, you create a list of constant
lists using (defvar L '((0 0 0 0) (0 0 0 0) (0 0 0 0))) then therein
lies your problem. The standard says that the behaviour experienced
when modifying a constant list (or any other constant object) is
undefined. In this case your compiler probably decided to coalesce the
constants into one. This would explain why when you modify one of the
lists all of them appear to change (since all three are indeed the
same list).

The correct way of creating the (non-constant) list L is this:

(defvar L (list (list 0 0 0 0) (list 0 0 0 0) (list 0 0 0 0)))


[some poorly formatted lisp code elided]

Btw, where did you learn your particular style of formatting Lisp
programs? It is highly irregular to put the closing bracket on its own
line. Most lispers will find such code difficult to read so in the
future when posting to this newsgroup please use commonly accepted
conventions. You can find out about these by looking at code examples
in any decent Common Lisp book or online tutorial.

PS. There is one more reason why your code will fail to give you the
answer you expect. Hint: in CL lists are indexed starting at 0.

From: Donovan Parks
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <af0pgg$pk0$1@casey.uvic.ca>
Thanks for the help.

I am creating my list with the following code (hopefully, the formatting is
more standard now):

(defun newBoard ()
    (let ((row) (board))
        (dotimes (i *numCol*)  (setq row (cons '0 row)))
        (dotimes (i *numRow*) (setq board (cons row board)))
        board))

Note, that *numCol* and *numRow* are global variables.  Now, the advantage
of this code is is produces a list of lists so I can use functions like nth,
first, rest, etc...  Is there a way I can create a list of list and not have
the list be of constants.  Can you point me to a good on-line source that
might help me with the difference between setq, defvar, etc...  I have been
using http://grimpeur.tamu.edu/~colin/lp/, but it doesn't explain a lot of
the LISP functions (i.e defvar).

I am completely new to LISP and this newsgroup.  Please let me know if these
questions are appropriate.

Regards,
Donovan Parks

>
> > Hello,
> >
> > I have a list of list in the following format:
> >     L = ((0 0 0 0) (0 0 0 0) (0 0 0 0))
> >
> > Now, I need to be able to change an arbitrary atom.  For example, I
> > would like to modify the list so that is becomes:
> >     L' = ((0 X 0 0) (0 0 0 0) (0 0 0 0))
> >
> > I thought I could do this using setf as follows:
> >     (setf (nth 2 (nth 1 L) 'X))
>
> There is another reason why the above won't work. In the outer call to
> NTH you pass it three arguments even though it only expects two. From
> now on I'll assume that you intended to write:
>
> (setf (nth 2 (nth 1 L)) 'X)
>
> > Unfortunately, this results in:
> >     L' = ((0 X 0 0) (0 X 0 0) (0 X 0 0))
>
> How do you create L? If, as I suspect, you create a list of constant
> lists using (defvar L '((0 0 0 0) (0 0 0 0) (0 0 0 0))) then therein
> lies your problem. The standard says that the behaviour experienced
> when modifying a constant list (or any other constant object) is
> undefined. In this case your compiler probably decided to coalesce the
> constants into one. This would explain why when you modify one of the
> lists all of them appear to change (since all three are indeed the
> same list).
>
> The correct way of creating the (non-constant) list L is this:
>
> (defvar L (list (list 0 0 0 0) (list 0 0 0 0) (list 0 0 0 0)))
>
>
> [some poorly formatted lisp code elided]
>
> Btw, where did you learn your particular style of formatting Lisp
> programs? It is highly irregular to put the closing bracket on its own
> line. Most lispers will find such code difficult to read so in the
> future when posting to this newsgroup please use commonly accepted
> conventions. You can find out about these by looking at code examples
> in any decent Common Lisp book or online tutorial.
>
> PS. There is one more reason why your code will fail to give you the
> answer you expect. Hint: in CL lists are indexed starting at 0.
From: Gabe Garza
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <k7osm0db.fsf@anubis.kynopolis.org>
"Donovan Parks" <······@uvic.ca> writes:

> Thanks for the help.
> 
> I am creating my list with the following code (hopefully, the formatting is
> more standard now):

   The formatting is more standard (though the indents are kinda big),
but the names are not. :) The Lisp way is to seperate the words in
variable names with hyphens, e.g., num-col (or even number-of-columns)
instead of numCol.

> (defun newBoard ()
>     (let ((row) (board))

  One school of thought is to always provide an initial value for a 
variable introduced with LET unless you explicitly assign it one before
you use it.  The way you've written it will work (because by default they're
bound to NIL, which is the empty list), but it could be more clearly written
like this:

   (let ((row '())
         (board '())

  The advantage of doing it this way is that the reader is immediately
clued-in to the fact that ROW and BOARD are empty lists and the code that
follows is probably going to be adding things to them.

>         (dotimes (i *numCol*)  (setq row (cons '0 row))) 
                                                  ^
  Numbers evaluate to themselves, so you don't need to quote the 0.

>         (dotimes (i *numRow*) (setq board (cons row board)))

  There's an operator called PUSH that you can use as a shorthand for
(setq board (cons row board)): (push row board).

>         board))
> 
> Note, that *numCol* and *numRow* are global variables.  Now, the advantage
> of this code is is produces a list of lists so I can use functions like nth,
> first, rest, etc... 

   Another aproach would be to use a two dimensional array, e.g.,

(defun new-board ()
  (make-array (list *number-of-columns* *number-of-rows*)
              :initial-element 0))

  Then you could use functions like AREF. ;)

> Is there a way I can create a list of list and not have the list be
> of constants.

  I don't really understand this--the only constant in the code you gave 
was 0, but numbers are immutable: if you assign something to a variable
that has a number bound to it, you're not changing the constant, only 
the binding of the variable (or contents of the CAR or CDR of a cons cell,
or the contents of a structure or class slot, or the contents of an 
array position, etc.).

> Can you point me to a good on-line source that
> might help me with the difference between setq, defvar, etc...  

DEFVAR establishes what you currently call a "global variable" but
what you'll later refer to as a "special variable"--the SPECIAL means
that it's dynamically scoped, but if you don't understand what that
means don't worry about it quite yet.

SETQ changes the binding of a variable, use it when you've already
defined a variable and want to change its binding (e.g., what it is
"set to").  Personally, I never use SETQ and always use SETF, which
behaves identically to SETQ when the first argument is a symbol but
also handles more generic situations, for example, you can use SETF
and AREF to change the contents of an array:

Command: (defvar *board* (make-array '(2 2) :initial-element 0))
*BOARD*
Command: *board*
#2A((0 0) (0 0))
Command: (setf (aref *board* 0 0) 42)
42
Command: *board*
#2A((42 0) (0 0))

> I have been
> using http://grimpeur.tamu.edu/~colin/lp/, but it doesn't explain a lot of
> the LISP functions (i.e defvar).

Have you found the ALU website yet? http://www.lisp.org has many good pointers
to introductory material.

> I am completely new to LISP and this newsgroup.  Please let me know if these
> questions are appropriate.

In general, people won't mind answering questions if you demonstrate
that you've put some thought and effort into answering them yourself.
In fact, if you demonstrate that you're making a genuine effort to
learn Lisp, you may find some happy to try and help you learn.

Gabe Garza
From: Alexey Dejneka
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <m3y9d7gaat.fsf@comail.ru>
Hellom

"Donovan Parks" <······@uvic.ca> writes:

> (setf (nth 2 (nth 1 L)) 'X)
> Unfortunately, this results in:
>      L' = ((0 X 0 0) (0 X 0 0) (0 X 0 0))

> I am creating my list with the following code (hopefully, the formatting is
> more standard now):
> 
> (defun newBoard ()
>     (let ((row) (board))
>         (dotimes (i *numCol*)  (setq row (cons '0 row)))
>         (dotimes (i *numRow*) (setq board (cons row board)))
>         board))

> there a way I can create a list of list and not have
> the list be of constants.

You have done it.

Your problem is that you are using the physically same list for all
rows, so when you are modifying one row, you do the same with all
others. Consider this simplified version:

=====
* (setq *x* (list 1 2 3))
(1 2 3)
* (setq *y* *x*)
;;; This does not copy list: *Y* refers to the same list as *X*.
(1 2 3)
* (setf (first *x*) 0)
0
* *x*
(0 2 3)
* *y*
(0 2 3)
=====

You should use COPY-LIST:

(defun newBoard ()
  (let ((row) (board))
    (dotimes (i *numCol*) (setq row (cons '0 row)))
    (dotimes (i *numRow*) (setq board (cons (copy-list row) board)))
    board))

or create each row independently:

(defun newBoard ()
  (let ((board))
    (dotimes (i *numRow*)
      (let ((row))
        (dotimes (i *numCol*)  (setq row (cons '0 row)))
        (setq board (cons row board))))
    board))


Regards,
Alexey Dejneka

---
"You've said you removed a bug. Why has the code grown?"
From: Pierpaolo BERNARDI
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <Yc%Q8.59320$TS.1651558@news1.tin.it>
"Donovan Parks" <······@uvic.ca> ha scritto nel messaggio ·················@casey.uvic.ca...
> Thanks for the help.
>
> I am creating my list with the following code (hopefully, the formatting is
> more standard now):
>
> (defun newBoard ()
>     (let ((row) (board))
>         (dotimes (i *numCol*)  (setq row (cons '0 row)))
>         (dotimes (i *numRow*) (setq board (cons row board)))
>         board))

You are using numRow copies of the same row.

Try this:

(defun new-board ()
  (let ((board '()))
    (dotimes (i *num-row*)
      (let ((row '()))
        (dotimes (i *num-col*)
          (setq row (cons 0 row)))
        (setq board (cons row board))))
    board))


or:

(defun new-board ()
  (let ((board '()))
    (dotimes (i *num-row*)
      (push (make-list *num-col*) board))
    board))


or:

(defun new-board ()
  (loop repeat *num-col*
        collect (make-list *num-col*)))


or better, use an array.

P.
From: Peter Buchlovsky
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <87ofe3xu5r.fsf@cs.bham.ac.uk>
"Donovan Parks" <······@uvic.ca> writes:

> Thanks for the help.
> 
> I am creating my list with the following code (hopefully, the
> formatting is more standard now):
> 
> (defun newBoard ()
>     (let ((row) (board))
>         (dotimes (i *numCol*)  (setq row (cons '0 row)))
>         (dotimes (i *numRow*) (setq board (cons row board)))
>         board))
> 
> Note, that *numCol* and *numRow* are global variables.  Now, the
> advantage of this code is is produces a list of lists so I can use
> functions like nth, first, rest, etc...  Is there a way I can create
> a list of list and not have the list be of constants.

In your code you're not actually creating any constant lists. I am
sorry that I jumped to the conclusion that you did. I think it was
something in the "L = ((0 0 0 0) (0 0 0 0) (0 0 0 0))" pseudo-code
which gave me this idea (looks like a short step from that to
"L = '((0 0 0 0) (0 0 0 0) (0 0 0 0))").

The problem is that you're reusing the list in the variable ROW so all
three inner lists are actually one and the same. As others have
already pointed out you can solve this by creating another copy of the
list first using the function COPY-LIST.

> Can you point me to a good on-line source that might help me with
> the difference between setq, defvar, etc...  I have been using
> http://grimpeur.tamu.edu/~colin/lp/, but it doesn't explain a lot of
> the LISP functions (i.e defvar).

The ALU website at www.lisp.org contains plenty of links to tutorials
and reference materials.

For reference I would highly recommend the Common Lisp Hyperspec
available from
http://www.xanalys.com/software_tools/reference/HyperSpec/

I found Successful Lisp to be a great online tutorial (although its
actually more of a book). You can find it at
http://psg.com/~dlamkins/sl/cover.html

-- 
Peter
From: Donovan Parks
Subject: Re: Using setf on a List of Lists (thanks)
Date: 
Message-ID: <af30so$2k02$1@casey.uvic.ca>
Hello,

Thanks to all those who kindly helped out.  I've now been able to solve the
problem I was facing and have learned a lot more about lisp in the process.
Thanks.

Donovan
From: Thomas F. Burdick
Subject: Re: Using setf on a List of Lists
Date: 
Message-ID: <xcvptyjnoab.fsf@apocalypse.OCF.Berkeley.EDU>
Peter Buchlovsky <·······@cs.bham.ac.uk> writes:

> The correct way of creating the (non-constant) list L is this:
> 
> (defvar L (list (list 0 0 0 0) (list 0 0 0 0) (list 0 0 0 0)))

You can do it that way, but personally, I would write:

  (defvar *l* (copy-tree '((0 0 0 0) (0 0 0 0) (0 0 0 0))))

COPY-TREE and COPY-LIST are my good friends :)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'