Основной вопрос о списке ассоциаций в Лиспе - PullRequest
13 голосов
/ 11 ноября 2010

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

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

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

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

Ответы [ 4 ]

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

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

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

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

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

(defparameter *edges* 
  '((living-room . ((garden west door)
                    (attic upstairs ladder)))
    (garden . ((living-room east door))) 
    (attic . ((living-room downstairs ladder))) ))
5 голосов
/ 11 ноября 2010

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))
1 голос
/ 11 ноября 2010

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

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

(cdr (assoc 'Foobar *edges*))

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

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

1 голос
/ 11 ноября 2010

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

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

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

Alist не является частью синтаксиса Lisp.Это просто список, так что вы можете поместить все, что хотите, в CDR каждого элемента.В данном случае это еще одна ячейка CONS.ASSOC просто смотрит на АВТОМОБИЛЬ каждого элемента.

(assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
...