Что такое определение Common Lisp Cons Cell? Какая ячейка Cons отличается от стандартного элемента связанного списка? В конце концов, как ячейка cons, так и связанный элемент списка имеют значение и указатель на следующую ячейку или элемент... или это понимание неверно?
Что такое определение Lisp Cons Cell?
Ответ 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, вам придется переопределить класс или структуру данных, чтобы изменить типы.