Common Lisp Минусы создает список из двух символов, Clojure Минусы требует Seq для минусов? - PullRequest
14 голосов
/ 11 июля 2010

(Отказ от ответственности - я знаю о значении Seqs в Clojure)

В общем lisp функцию cons можно использовать для объединения двух символов в список:

(def s 'x)
(def l 'y)
(cons s l)

В clojure - вы можете использовать только против последовательности - минусы не были расширены для работы с двумя символами.Поэтому вы должны написать:

(def s 'x)
(def l 'y)
(cons s '(l))

Есть ли в Clojure шаблон более высокого уровня, объясняющий эту разницу между Common LISP и Clojure?

Ответы [ 5 ]

9 голосов
/ 11 июля 2010

В Clojure, в отличие от традиционных Лиспов, списки не являются первичными структурами данных. Структуры данных могут реализовывать интерфейс ISeq , который является другим представлением структуры данных, который он предоставляет, позволяя тем же функциям получать доступ к элементам в каждом. (Списки уже реализуют это. seq? проверяет, реализует ли что-то ISeq . (seq? '(1 2)), (seq? [1 2])) Clojure просто действует иначе (по уважительной причине), в том смысле, что когда используется cons, последовательность (на самом деле она имеет тип Возвращается clojure.lang.Cons), построенное из a и (seq b). (a является аргументом 1 и b аргументом 2) Очевидно, что символы не реализуют и не могут реализовывать ISeq .

Clojure.org / последовательность

Ролик Хикки Скринкаст о секвенциях. Тем не менее, обратите внимание, что rest изменился, и его предыдущее поведение теперь в next, а lazy-cons заменено на lazy-seq и cons.

clojure.lang.RT

6 голосов
/ 11 июля 2010

В Common Lisp CONS создает так называемую ячейку CONS, которая похожа на запись с двумя слотами: 'car' и 'cdr'.

Вы можете положить НИЧЕГО в эти два слота ячейки против.

Минусы ячейки используются для создания списков. Но можно создать все виды структур данных с объединенными ячейками: деревья, графики, различные типы специализированных списков, ...

Реализации Lisp высоко оптимизированы для обеспечения очень эффективных cons-ячеек.

3 голосов
/ 12 июля 2010

В Clojure предпочтительнее использовать двухэлементный вектор: [:a :b].Под капотом такие маленькие векторы реализованы как массивы Java и являются чрезвычайно простыми и быстрыми.

Сокращение для (cons :a '(:b)) (или (cons :a (cons :b nil))) равно list: (list :a :b).

3 голосов
/ 11 июля 2010

Список Lisp - это просто распространенный способ использования cons-ячеек (см. Описание Райнера ). Clojure лучше всего рассматривать как отсутствие минусов (хотя что-то подобное может скрываться под капотом). Clojure cons - это неправильное название, на самом деле его просто нужно назвать prepend.

2 голосов
/ 11 июля 2010

Когда вы говорите

> (cons 'a 'b)

в общем lisp, вы получаете не список, а пару с точками: (a . b), тогда как результат

> (cons 'a (cons 'b nil))

- это пара с точками (a . ( b . nil)).

В первом списке cdr() этого не является списком, поскольку он здесь b, а не nil, что делает его неправильным списком.Правильные списки должны заканчиваться nil.Поэтому функции более высокого порядка, такие как mapcar(), и друзья не будут работать, но мы сохраняем cons-ячейку.Я предполагаю, что дизайнеры Clojure удалили эту функцию из-за путаницы, которую она могла вызвать.

...