Что такое определение Lisp Cons Cell?

Что такое определение Common Lisp Cons Cell? Какая ячейка Cons отличается от стандартного элемента связанного списка? В конце концов, как ячейка cons, так и связанный элемент списка имеют значение и указатель на следующую ячейку или элемент... или это понимание неверно?

Ответ 1

Консервные ячейки вообще содержат два указателя, которые могут указывать на что угодно. Общее использование курса состоит в том, чтобы указать "значение" на левое, а на другую ячейку Cons (или nil) с "правильным".

Ответ 2

Ячейка cons ближе к двоичному дереву node, чем связанный список node. автомобиль и cdr возвращают двух детей, которые могут быть nil, атомы или другие ячейки cons.

Ответ 3

В Lisp ячейка cons содержит пару значений. Если ячейка cons находится в переменной c, то (car c) возвращает первое значение, а (cdr c) возвращает вторую.

По соглашению список состоит из cons-ячеек, где car ячейки содержит значение node, а cdr содержит ссылку на следующий node или nil (пустой список), чтобы указать конец списка. Когда примитивные функции возвращают или принимают списки, это формат, в котором представлен список.

Следовательно, для списка l, (car l) появляется первый элемент (значение в первой ячейке cons cons), а (cdr l) возвращает хвост списка (следующая ячейка cons в списке).

Ответ 4

A cons - одна треть контракта, состоящего из cons, car и cdr, причем требование состоит в том, что они ведут себя как пары, как упомянули другие.

Причиной отказа от слов "ссылка", "указатель" и т.д. из этого определения является признание того, что это детали реализации. Если бы вы захотели, вы могли бы построить cons из воздуха, как это делали Абельсон и Суссман:

(define (cons a b) (lambda (x) (x a b)))
(define (car x) (x (lambda (a b) a)))
(define (cdr x) (x (lambda (a b) b)))

Это определение полностью живет в мире определений и функций Lisp и даже не останавливается на том, сохраняются ли объекты в виде значений или ссылок; но они могут служить заменой для примитивных объектов (не считая изменчивости или других специальных применений).

Ответ 5

Я думаю, что другие ответы здесь, хотя и точны, не являются явным об одном.

В традиционной реализации С++ связанных списков набираются два поля (val и next, скажем). next определяется как указывающий на другой node в списке, причем null является терминатором. Вы не можете указать ничего, кроме другого node с next.

Lisps динамически типизируются, поэтому любое поле в ячейке cons может быть любым (либо атомом, либо ссылкой). Вы можете реализовать связанный список с cons-ячейками (весь список Lisp: цепочка cons-ячеек с терминатором nil), но вы также можете поместить произвольные значения в каждое поле, используя ячейку cons в качестве координаты пара, дерево node и т.д.

Вы можете даже комбинировать их; например, список координат x y:

;; (cons foo (cons bar nil)) == (list foo bar)    
(cons
  (cons 5 4)
  (cons (cons 9 10) nil))
=>
((5 . 4) (9 . 10))

Концевая ячейка, таким образом, является строго более общей, чем связанный список node; так сказать, ближе к "прикладной паре". Все стандартные функции обработки списка (map, dolist и т.д.) - это просто функции, предполагающие, что вы помещаете значения в car и еще один список в cdr.

Все это означает, что - если бы вы пожелали - вы могли бы определять списки назад, а car указывали на следующую ячейку cons cons и cdr, указывающую на значение! Чтобы сделать это со связанным списком node, вам придется переопределить класс или структуру данных, чтобы изменить типы.