Я не попробовал текущую реализацию, но я слышал, что официальная поддержка LINQ будет идти с NHibernate 2.1, таким образом, я ожидал бы этого, если Вы хотите избежать каких-либо грубых краев...
Ячейки Cons обычно содержат два указателя, которые могут указывать на что угодно. Обычно используется, конечно, чтобы указать на «значение» с помощью левой, и на другую ячейку Cons (или ноль) с «правой».
Консольная ячейка ближе к узлу двоичного дерева, чем узел связанного списка. car и cdr возвращают двух дочерних элементов, которые могут быть нулевыми, атомами или другими cons-ячейками.
В Лиспе cons-ячейка содержит пару значений. Если cons-ячейка находится в переменной c
, то (car c)
возвращает первое значение, а (cdr c)
возвращает второе.
By По соглашению, список состоит из cons-ячеек, где car
ячейки содержит значение узла, а cdr
содержит ссылку на следующий узел или nil (пустой список), чтобы указать конец списка. Когда примитивные функции возвращают или принимают списки, это формат, в котором представлен список.
Следовательно, для списка l
, (car l)
дает первый элемент (значение в первой cons-ячейке) и (cdr l)
возвращает хвост списка (следующая cons-ячейка в списке).
A минусы Ячейка
- это треть контракта, состоящего из cons
, car
и cdr
, с требованием, чтобы они вели себя парами, как другие
Причина исключения слов «ссылка», «указатель» и т. д. из этого определения состоит в том, чтобы признать, что это детали реализации. При желании вы могли бы создать минусы
из воздуха, как это сделали Абельсон и Сассман:
(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)))
Это определение полностью живет в мире определений и функций Лиспа и даже не перестает рассматривать хранятся ли объекты как значения или ссылки;
Я думаю, что другие ответы здесь, хотя и точны, не являются явными в одном.
В традиционной реализации связанного списка C ++ два поля ( val
и next
, скажем) набраны . next
определяется как указывающий на другой узел в списке, где null
является символом конца. Вы не можете указать ни на что , кроме другой узел с next
.
Lisp динамически типизируется, поэтому любое поле в cons-ячейке может быть чем угодно ( либо атом, либо ссылка). Вы можете реализовать связанный список с cons-ячейками (это все, что представляет собой список Lisp: цепочка cons-ячеек с терминатором nil
), но вы также можете помещать произвольные значения в каждое поле, используя cons-ячейку как пара координат, узел дерева и т. д.
Вы даже можете комбинировать их; например, список координат x
y
:
;; (cons foo (cons bar nil)) == (list foo bar)
(cons
(cons 5 4)
(cons (cons 9 10) nil))
=>
((5 . 4) (9 . 10))
Таким образом, cons-ячейка является строго более общей, чем узел связанного списка; это ближе к "прикладной паре", так сказать. Все стандартные функции обработки списков ( map
, dolist
и т. Д.) - это просто функции, которые предполагают , что вы помещаете значения в car
] и еще один список в cdr
.
Все это означает, что - при желании - вы можете определять списки в обратном порядке , где car
указывает на следующую cons-ячейку, а cdr
указывает на значение! Чтобы сделать это с помощью узла связанного списка, вам придется переопределить класс или структуру данных, чтобы изменить типы.