dptd
dptd

Reputation: 274

How to create dotted pair with nil

I have a list of queue names in the following form:

'("foo" "bar")

I am trying to store queues as assoc list in the following way:

'(("foo" . nil) ("bar" . nil))

Basically it is an assoc list with queues "foo" and "bar" which are currently empty. When Bob and Alice will be in the "foo" queue it should look like the following.

'(("foo" . ("alice" "bob")) ("bar" . nil))

How can I create this structure? I tried to achieve that by writing:

(mapcar #'(lambda (x) (cons x ''nil)) '("foo" "bar"))

which returned

'(("foo" QUOTE NIL) ("bar" QUOTE NIL))

this is probably not what I wanted because when I tried to push Bob to the "foo" queue it doesn't work as I wanted.

* (setf *tmp* '(("foo" . 'nil) ("bar" . 'nil)))
(("foo" QUOTE NIL) ("bar" QUOTE NIL))
* (push "bob" (caddr (assoc "foo" *tmp* :test #'string=)))
* *tmp*
(("foo" QUOTE ("bob")) ("bar" QUOTE NIL))

How can I create dotted pair with empty list after the dot?

EDIT: Actually when I store such assoc list as the class slot it looks fine.

* (describe myClassInstance)
;; ...
QUEUES    = (("foo" . 'NIL) ("bar" . 'NIL))
;; ...

However after writing adding Bob to the "foo" queue all queues are being changed.

* (push "bob" (caddr (assoc "foo" (slot-value myClassInstance 'testClass::queues) :test #'string=))))
* (describe myClassInstance)
;; ...
QUEUES    = (("foo" . '("bob") ("bar" . '("bob"))
;; ...

What just happened here? It looks like the cdr part of all the queues was a single symbol and when I changed it's value in one place ("foo" queue) then it was changed in all the places (all the queues). Does it make any sense?

Upvotes: 0

Views: 485

Answers (3)

Rainer Joswig
Rainer Joswig

Reputation: 139261

Compare with dots

CL-USER 48 > (sdraw '(("foo" . ("alice" "bob")) ("bar" . nil)))

[*|*]---------------------------->[*|*]--->NIL
 |                                 |
 v                                 v
[*|*]--->[*|*]---->[*|*]--->NIL   [*|*]--->NIL
 |        |         |              |
 v        v         v              v
"foo"    "alice"   "bob"          "bar"

and without dots

CL-USER 49 > (sdraw '(("foo" "alice" "bob") ("bar")))

[*|*]---------------------------->[*|*]--->NIL
 |                                 |
 v                                 v
[*|*]--->[*|*]---->[*|*]--->NIL   [*|*]--->NIL
 |        |         |              |
 v        v         v              v
"foo"    "alice"   "bob"          "bar"

So, both notations are describing the same cons structure.

Upvotes: 2

Svante
Svante

Reputation: 51501

A cons where the cdr is nil is exactly the same as a one-element list. This is how lists are defined.

In other words, (cons x nil) is the same as (list x). You can imagine the result like this:

+-------+
| x |nil|
+-------+

A dotted pair where the cdr is a list is thus also just a list.

In other words, '(("foo" . nil) ("bar" . nil)) is exactly the same as '(("foo") ("bar")), even if the former notation perhaps better conveys your intent of treating it as an alist.

In the same way, '(("foo" . ("alice" "bob")) ("bar" . nil)) is exactly the same as '(("foo" "alice" "bob") ("bar")).

This means that you can create your data structure exactly as you want, but you can use e. g. list instead of (lambda (x) (cons x nil)) (which is the same for a single argument).

(defun make-queues (&rest names)
  (mapcar #'list names))

You can also just push to the element found by assoc under a name:

(defun add-to-queue (queues queue-name item)
  (push item (cdr (assoc queue-name queues :test #'equal))))

(defun get-queue (queues queue-name)
  (cdr (assoc queue-name queues :test #'equal)))

The problem that you had last was that you put a literal into a list and tried to modify it: you put the same literal list containing only nil into each element of your alist.

Upvotes: 4

Leo
Leo

Reputation: 1934

I think you are probably confusing the structure with its printed representation. (cons x nil) is the same as '(x . nil) and the same as '(x). They will all print as (x).

If you want to print as '(x . nil) you can write a print function for it, but the representations is perfectly fine.

Upvotes: 5

Related Questions