2016-11-13 4 views
0

У меня есть список имен очереди в следующем виде:Как создать пунктирную пару с нулевой

'("foo" "bar") 

Я пытаюсь хранить очереди в списке ДООСА следующим образом:

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

В основном это список участников с очередями «foo» и «bar», которые в настоящее время пустые. Когда Боб и Алиса будут в очереди «foo», он должен выглядеть следующим образом.

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

Как создать эту структуру? Я пытался добиться того, что написав:

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

который вернулся

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

это, вероятно, не то, что я хотел, потому что, когда я попытался оттолкнуть Боба к «Foo» очереди он не работает Я хотел.

* (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)) 

Как создать точную пару с пустым списком после точки?

EDIT: Фактически, когда я храню такой список ассоциаций, как слот класса, он выглядит нормально.

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

Однако после написания добавления Боба в очередь «foo» все очереди меняются.

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

Что здесь произошло? Похоже, что часть всех очередей была единственным символом, и когда я изменил ее значение в одном месте (очередь «foo»), то он был изменен во всех местах (все очереди). Это имеет смысл?

+0

Что такое '(cons x '' nil)' ??? Почему ниль цитируется дважды? –

+0

Что такое '' (foo. 'Nil) 'должно быть? Почему ниль цитируется? –

+0

@RainerJoswig Я не могу найти источник сейчас, но было место, где я нашел этот способ получить пунктирную пару с нулем в конце. Вероятно, это проблема, но я не могу понять, как создать точную пару с пустым списком после точки. – dptd

ответ

4

Против, где cdr равно нулю, точно такое же, как и список из одного элемента. Вот как определяются списки.

Иными словами, (cons x nil) - это то же самое, что и (list x). Вы можете себе представить результат следующим образом:

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

Точечная пара, где cdr является списком, является, таким образом, также просто списком.

Иными словами, '(("foo" . nil) ("bar" . nil)) точно такой же, как '(("foo") ("bar")), даже если прежняя нотация, возможно, лучше передает ваше намерение рассматривать его как алиста.

Точно так же '(("foo" . ("alice" "bob")) ("bar" . nil)) в точности совпадает с '(("foo" "alice" "bob") ("bar")).

Это означает, что вы можете создать свою структуру данных точно так, как хотите, но вы можете использовать e. г. list вместо (lambda (x) (cons x nil)) (что одинаково для одного аргумента).

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

Вы также можете просто нажать на элемент, найденный assoc под названием:

(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))) 

Проблема, которую вы имели в прошлом, что вы положили буквальную в список и попытался изменить его: вы помещаете тот же литеральный список, содержащий только nil в каждый элемент вашего алиста.

+0

Это потрясающе. Большое вам спасибо за то, что разъяснил это мне таким ясным образом. Итак, в основном каждый список является алистом? Потому что даже одноэлементный список содержит «скрытый» «nil» после точки? – dptd

+0

Нет, alist - это список conses. Список - это минус или ноль (пустой список). Таким образом, любой список непустых списков также является алистом. – Svante

5

Я думаю, что вы, вероятно, путаете структуру с ее напечатанным представлением. (cons x nil) - это то же самое, что и '(x . nil) и то же, что и '(x). Все они будут напечатаны как (x).

Если вы хотите напечатать как '(x . nil), вы можете написать для него функцию печати, но представления отлично.

+0

Это имеет смысл, спасибо. – dptd

2

Сравнить с точками

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

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

и без точек

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

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

Таким образом, оба обозначения описывают ту же самую структуру минусы.

+0

Спасибо! Как-то большую часть времени я забываю об удивительном 'sdraw'. – dptd