Неожиданный вывод с cons () - PullRequest
11 голосов
/ 14 августа 2010

Я из императорского прошлого, но в наши дни пробую себя в LISP (Common LISP)

Я читаю здесь о cons, что

(минусы х л):

Учитывая объект LISP x и список L, при оценке (cons x L) создается список, содержащий x, за которым следуют элементы в L.

Когда я намеренно не использовал список в качестве второго аргумента, т.е. когда я использовал

(cons 'a 'a) Я ожидал ошибки, но оу! Я получил (A . A).

Что я пропустил и что такое (A . A)?

Ответы [ 3 ]

7 голосов
/ 14 августа 2010

Cons создает «клетку против».Поначалу это не имеет ничего общего со списками.Минус ячейка - это пара двух значений.Cons-ячейка представлена ​​в письменной форме «пунктирной парой», например, (A . B), которая содержит два значения 'A и 'B.

Два места в cons-ячейке называются «car»."и" CDR ".Вы можете визуализировать такую ​​cons-ячейку как разделенный на две части блок:

  car   cdr
+-----+-----+
|  A  |  B  |
+-----+-----+

В Lisp значение также может быть ссылкой на что-то еще, например, на другую cons-ячейку:

+-----+-----+       +-----+-----+
|  A  |   --------> |  B  |  C  |
+-----+-----+       +-----+-----+

Это будет представлено в виде «пунктирной пары» как (A . (B . C)).Вы можете продолжать так:

+-----+-----+       +-----+-----+       +-----+-----+
|  A  |   --------> |  B  |   --------> |  C  |  D  |
+-----+-----+       +-----+-----+       +-----+-----+

Это (A . (B . (C . D))).Как вы можете видеть, в такой структуре значения всегда находятся в car в ячейке cons, а cdr указывает на остальную часть структуры.Исключением является последнее значение, которое находится в последнем cdr.Нам не нужно это исключение: в Лиспе есть специальное значение NIL, которое обозначает «ничего».Поместив NIL в последний cdr, вы получите удобное значение часового, и все ваши значения будут в car s:

+-----+-----+       +-----+-----+       +-----+-----+       +-----+-----+
|  A  |   --------> |  B  |   --------> |  C  |   --------> |  D  | NIL |
+-----+-----+       +-----+-----+       +-----+-----+       +-----+-----+

Вот каксписок построен в Лиспе.Поскольку (A . (B . (C . (D . NIL)))) немного громоздкий, его также можно представить просто как (A B C D).NIL также называется пустым списком ();это заменяемые записи для одной и той же вещи.

Теперь вы можете понять, почему (cons x list) возвращает другой список.Cons просто создает другую ячейку с x в car и ссылкой на list в cdr:

+-----+-----+
|  X  |   --------> list
+-----+-----+

, а если list равно (A B), этоработает следующим образом:

+-----+-----+       +-----+-----+       +-----+-----+
|  X  |   --------> |  A  |   --------> |  B  | NIL |
+-----+-----+       +-----+-----+       +-----+-----+

Таким образом, (cons x '(a b)) оценивается как (x a b).

Списки - это всего лишь одно из наиболее распространенных применений cons-ячеек.Вы также можете создавать произвольные деревья из cons-ячеек, круговых списков или любого ориентированного графа.

1 голос
/ 14 августа 2010

(CONS x L)

Учитывая x и L, CONS возвращает новую cons-ячейку с x как CAR этой ячейки и L как CDR этой ячейки.

Списки - это связанные цепочки клеток cons.

CL-USER 141 > (sdraw '(a b c))

[*|*]--->[*|*]--->[*|*]---> NIL
  |        |        |
  v        v        v
  A        B        C

CL-USER 142 > (sdraw (cons 'foo '(a b c)))

[*|*]--->[*|*]--->[*|*]--->[*|*]---> NIL
  |        |        |        |
  v        v        v        v
 FOO       A        B        C

Если CONS получает два символа в качестве аргумента, он выглядит следующим образом:

CL-USER 143 > (sdraw (cons 'foo 'bar))

[*|*]---> BAR
  |
  v
 FOO
1 голос
/ 14 августа 2010

'a - это атом lisp, а (A . A) - вырожденный список, называемый cons-ячейкой или "точечной парой". Поскольку вы не передали список аргументов L в (cons x L), вы вернули ячейку.

...