Основной вопрос о списке ассоциаций в Лиспе

Я читаю "Землю Лиспа" (кстати, одну из лучших технических книг, которые я когда-либо читал), и мне попался список ассоциаций.

  (defparameter *edges* 
     '((living-room (garden west door) 
                    (attic upstairs ladder))
      (garden (living-room east door)) 
      (attic (living-room downstairs ladder))))

Во-первых, является ли список ассоциаций в Лиспе той же концепцией Java Map (привязка ключ-значение)?
Для ключа от гостиной, как можно иметь более одного значения? почему бы не заключить значение в список:

    (living-room ((garden west door) (attic upstairs ladder)))

4 ответа

Решение
  1. Да, список ассоциаций является одним из способов выражения ассоциаций ключ-значение. Другими структурами, которые предоставляет Common Lisp для этой цели, являются списки свойств и хеш-таблицы.

  2. Значение на самом деле уже содержится в списке. Alist - это, по сути, список пар, где ключом является автомобиль каждой пары, а cdr - это значение, связанное с этим ключом. Если вы посмотрите на ключ LIVING-ROOM с ASSOC и примените CDR к результату:

CL-USER> (cdr (ассоциированная гостиная * ребра *))
((САД ЗАПАДНАЯ ДВЕРЬ) (ТРЕТЬЯ ЛЕСТНИЦА НАВЕРХ))

Волшебство за этим заключается в том, что пара, чья машина living-room и чей CDR является списком двух элементов (garden west door) а также (attic upstairs ladder) может также рассматриваться как список из трех элементов (living-room (garden west door) (attic upstairs ladder))из-за того, что списки построены из пар.

Обычно при представлении списков в виде объектов в кавычках вы видите элементы, явно изображенные точечными парами, а не обозначения списком, например:

(дефараметр * ребра * 
  '((гостиная. ((западная дверь сада)
                    (мансардная лестница наверх)))
    (сад. ((гостиная восточная дверь))) 
    (чердак. ((лестница в гостиную внизу)))))

ASSOC возвращает cons-ячейку и, таким образом, включает как ключ, так и значение.

Причина в том, что это позволяет легко обновить значение (или ключ) деструктивно.

Здесь обновление скрыто за SETF:

CL-USER 11 > (defparameter *edges* 
               (copy-tree
                '((living-room (garden west door) 
                               (attic upstairs ladder))
                  (garden (living-room east door)) 
                  (attic (living-room downstairs ladder)))))
*EDGES*

CL-USER 12 > (assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

CL-USER 13 > (cdr (assoc 'living-room *edges*))
((GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

CL-USER 14 > (setf (cdr (assoc 'living-room *edges*)) '((garden east door)))
((GARDEN EAST DOOR))

CL-USER 15 > (cdr (assoc 'living-room *edges*))
((GARDEN EAST DOOR))

Список ассоциаций похож на концепцию карты, поскольку оба ассоциированных ключа со значениями.

Нет необходимости заключать несколько значений в другой список, потому что это меняет значение значения. Я не знаком с этой книгой, но похоже, что *EDGES* определяется, автор хочет

(cdr (assoc 'Foobar *edges*))

быть списком мест, которые вы можете получить от Foobar. Как определено, это верно, если есть одно или несколько значений.

Если при наличии нескольких значений вы вложили эти значения в другой список, то вам просто нужно будет выбрать их из этого списка, когда вы захотите их использовать. Это не даст вам ничего, и это будет отличаться от случая с одним значением.

Во-первых, является ли список ассоциаций в Лиспе той же концепцией Java Map (привязка ключ-значение)?

Карта Java - это интерфейс. Alist- это особый способ использования (связанного) списка для хранения пар ключ-значение. Я не думаю, что в Java есть какие-либо встроенные Карты, имеющие те же свойства, что и в alist, но написать их будет несложно. Поскольку alist является списком, все функции и свойства списков по-прежнему сохраняются.

Для ключа от гостиной, как можно иметь более одного значения? почему бы не заключить значение в список:

Alist не является частью синтаксиса Lisp. Это просто список, так что вы можете поместить все, что хотите, в CDR каждого элемента. В данном случае это еще одна ячейка CONS. ASSOC просто смотрит на автомобиль каждого элемента.

(assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
Другие вопросы по тегам