Common Lisp Минусы создает список из двух символов, Clojure Минусы требует Seq для минусов?
(Отказ от ответственности - я знаю о значении Seqs в Clojure)
В общем случае функция 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 ответов
В отличие от традиционных Лиспов, в Clojure списки не являются основными структурами данных. Структуры данных могут реализовывать интерфейс ISeq, который представляет собой другое представление структуры данных, которую он предоставляет, позволяя тем же функциям получать доступ к элементам в каждом из них. (Списки уже реализуют это. seq?
проверяет, реализует ли что-то ISeq.(seq? '(1 2)), (seq? [1 2]))
Clojure просто действует иначе (по уважительной причине), в том случае, если cons
используется последовательность (это на самом деле типа clojure.lang.Cons
) построен из a
а также (seq b)
возвращается (a
будучи аргументом 1 и b
arg 2) Очевидно, что символы не реализуют и не могут реализовать ISeq.
Скринкаст / разговор Ричей Хикки, однако, обратите внимание, что rest
изменилось, и его предыдущее поведение теперь в next
и что lazy-cons
был заменен lazy-seq
а также cons
,
В Common Lisp CONS создает так называемую ячейку CONS, которая похожа на запись с двумя слотами: "car" и "cdr".
Вы можете положить НИЧЕГО в эти два слота камеры.
Клетки минусов используются для построения списков. Но можно создать все виды структур данных с объединенными ячейками: деревья, графики, различные типы специализированных списков, ...
Реализации Lisp высоко оптимизированы, чтобы обеспечить очень эффективные cons-ячейки.
Список Lisp - это просто распространенный способ использования cons-ячеек (см . Описание Райнера). Clojure лучше всего рассматривать как отсутствие минусов (хотя нечто подобное может скрыться под капотом). Clojure cons
это неправильное название, на самом деле его просто нужно назвать prepend
,
В Clojure предпочтительным является использование двухэлементного вектора: [:a :b]
, Под капотом такие маленькие векторы реализованы как массивы Java и являются чрезвычайно простыми и быстрыми.
Короткая рука для (cons :a '(:b))
(или же (cons :a (cons :b nil))
) является list
: (list :a :b)
,
Когда ты сказал
> (cons 'a 'b)
в общем случае вы получаете не список, а пару точек: (a . b)
тогда как результат
> (cons 'a (cons 'b nil))
это пунктирная пара (a . ( b . nil))
,
В первом списке cdr()
этого не список, так как он здесь b
и не nil
составляя неправильный список. Правильные списки должны быть прекращены nil
, Поэтому функции более высокого порядка, такие как mapcar()
и друзья не будут работать, но мы сохраняем камеру. Я предполагаю, что дизайнеры Clojure удалили эту функцию из-за путаницы, которую это могло вызвать.