Lisp HUG Maillist Archive

2 questions: make-list and hash-table

Hello,


Question 1:

when I create a list with like

(setf a (make-list 10 :initial-element '(0 0)))

then the command

setf (second (nth 4 a)) 3)

creates var _a_ as

((0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3))

why does setf (second (nth 4 a)) 3) concern every nth in the sense of (first (second (nth x a)) ?

Having read CLtL p. 418 (and Graham) I simply don't understand the situation.

Question 2:

I try to figure out the details of the loop macro with hash-tables (I know of other possibilities but now I'm interested only in this).

Some tutorials taught me that this works (and it does in LW):
  • (setf h (make-hash-table))
  • (setf (gethash 'a h) 1)
  • (setf (gethash 'b h) 2)
  • loop for k being the hash-key of h do (print k))

But when I try to get the hash-val together with the key-val with

(loop for k being the hash-key using (hash-value v) of h do (format t "~a ~a~%" k v))

then I get an error message from LW: Error: Unknown LOOP keyword in (... LOOP::OF H DO (FORMAT T "~a ~a~%" K V)).

Having read the passages in CLtL p. 723 I can't find a solution (in the sense of a very similar formulation - not maphash or other loop-constructions).

Many thanks for any advice.

Best,

Max


Re: 2 questions: make-list and hash-table

On Tue, 11 Jul 2006 20:50:57 +0200, Max Haas <Max.Haas@unibas.ch> wrote:

> Question 1:
>
> when I create a list with like
>
> (setf a (make-list 10 :initial-element '(0 0)))
>
> then the command
>
> setf (second (nth 4 a)) 3)
>
> creates var _a_ as
>
> ((0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3))
>
> why does setf (second (nth 4 a)) 3) concern every nth in the sense
> of (first (second (nth x a)) ?
>
> Having read CLtL p. 418 (and Graham) I simply don't understand the
> situation.

You've initialized the list with 10 "pointers" (in the sense of
languages like C) to the /same/ literal '(0 0).  If you modify one of
them, you modify them all (because they're all the same).  Try

  (eq (first a) (second a))

What you want is something like this:

  (setq a (loop repeat 10 collect (list 0 0)))

> Question 2:
>
> I try to figure out the details of the loop macro with hash-tables (I
> know of other possibilities but now I'm interested only in this).
>
> Some tutorials taught me that this works (and it does in LW):
> (setf h (make-hash-table))
> (setf (gethash 'a h) 1)
> (setf (gethash 'b h) 2)
> loop for k being the hash-key of h do (print k))
>
> But when I try to get the hash-val together with the key-val with
>
> (loop for k being the hash-key using (hash-value v) of h do (format t
> "~a ~a~%" k v))
>
> then I get an error message from LW: Error: Unknown LOOP keyword in
> (... LOOP::OF H DO (FORMAT T "~a ~a~%" K V)).
>
> Having read the passages in CLtL p. 723 I can't find a solution (in
> the sense of a very similar formulation - not maphash or other loop-
> constructions).

You've got the syntax wrong.  Try this:

  (loop for k being the hash-keys of h
        using (hash-value v)
        do (format t "~a ~a~%" k v))

Cheers,
Edi.


Re: 2 questions: make-list and hash-table


Max Haas <Max.Haas@unibas.ch> writes:
> (setf a (make-list 10 :initial-element '(0 0)))
> (setf (second (nth 4 a)) 3)
>
> creates var _a_ as
>
> ((0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3))
> why does setf (second (nth 4 a)) 3) concern every nth 

Because make-list is using the same exact initial-element everytime,
not a copy.  That is, they are sharing the same list structure.  Maybe
using a named variable will make this a bit clearer:

(setf xx (list 0 0))
(setf aa (make-list 10 :initial-element xx))
xx => (0 0)
(setf (second (nth 4 aa)) 3) => 3
xx => (0 3)
aa => ((0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3))

Put it another way: The list is 10 pointers/references to the same
object.

Depending on what you want to do, you might choose a different
initialization method.

> I try to figure out the details of the loop macro with hash-tables

Sorry, I'm a LOOP know-nothing.

Cheers,
Chris Dean


Re: 2 questions: make-list and hash-table

Max Haas wrote:
> Hello,
>
>
> Question 1:
>
> when I create a list with like
>
> (setf a (make-list 10 :initial-element '(0 0)))
>
> then the command
>
> setf (second (nth 4 a)) 3)
>
> creates var _a_ as
>
> ((0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3) (0 3))
>
> why does setf (second (nth 4 a)) 3) concern every nth in the sense of 
> (first (second (nth x a)) ?
>
> Having read CLtL p. 418 (and Graham) I simply don't understand the 
> situation.
>
> Question 2:
>
> I try to figure out the details of the loop macro with hash-tables (I 
> know of other possibilities but now I'm interested only in this).
>
> Some tutorials taught me that this works (and it does in LW):
>
>     * (setf h (make-hash-table))
>     * (setf (gethash 'a h) 1)
>     * (setf (gethash 'b h) 2)
>     * loop for k being the hash-key of h do (print k))
>
>
> But when I try to get the hash-val together with the key-val with
>
> (loop for k being the hash-key using (hash-value v) of h do (format t 
> "~a ~a~%" k v))
>
> then I get an error message from LW: Error: Unknown LOOP keyword in 
> (... LOOP::OF H DO (FORMAT T "~a ~a~%" K V)).
>
> Having read the passages in CLtL p. 723 I can't find a solution (in 
> the sense of a very similar formulation - not maphash or other 
> loop-constructions).
>
> Many thanks for any advice.
>
> Best,
>
> Max
>
>
The reason is that you are inserting _the same_ element in every place 
in your array; '(0 0) is a constant essentially.  If you want 
different-but-equal elements in your array, you'll need something along 
the lines of

(let ((size 10))
  (setf *a* (make-array size
                        :initial-contents (loop repeat size
                                                collect (list 0 0)))))

(Not tested, I don't have a running Lisp right now)

-Klaus.


Updated at: 2020-12-10 08:48 UTC