Общий lisp cons создает список из двух символов, clojure cons требует seq to cons на?
(Отказ от ответственности - я знаю о значении 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?
Ответы
Ответ 1
В Clojure, в отличие от традиционных Lisps, списки не являются основными структурами данных. Структуры данных могут реализовывать интерфейс ISeq - это другой вид структуры данных, которую он дал, позволяя тем же функциям обращаться к элементам в каждый. (Списки уже реализуют это. seq?
проверяет, реализует ли что-то ISeq. (seq? '(1 2)), (seq? [1 2]))
Clojure просто действует по-разному (без уважительной причины), в том случае, когда используется cons
, возвращается последовательность (она фактически типа clojure.lang.Cons
), построенная из a
и (seq b)
. (a
- arg 1 и b
arg 2) Очевидно, символы не реализуют и не могут реализовать ISeq.
Clojure.org/sequences
Последовательность screencast/talk от Rich Hickey Однако обратите внимание, что rest
изменилось, и предыдущее поведение теперь находится в next
, и что lazy-cons
был заменен на lazy-seq
и cons
.
clojure.lang.RT
Ответ 2
В Common Lisp CONS создает так называемую ячейку CONS, которая похожа на запись с двумя слотами: "автомобиль" и "cdr".
Вы можете помещать НИЧЕГО в эти два слота ячейки cons.
Ячейки Cons используются для создания списков. Но можно создавать все виды структур данных с cons-ячейками: деревья, графики, различные типы специализированных списков,...
Реализации Lisp сильно оптимизированы для обеспечения очень эффективных cons-ячеек.
Ответ 3
Список Lisp - это просто обычный способ использования cons-ячеек (см. описание Rainer). Clojure лучше всего воспринимать как не имеющую cons-клеток (хотя что-то подобное может скрываться под капотом). Clojure cons
является неправильным, его на самом деле просто называть prepend
.
Ответ 4
В Clojure предпочтительнее использовать двухэлементный вектор: [:a :b]
. Под капотом такие маленькие векторы реализованы как массивы Java и чрезвычайно просты и быстры.
Коротка для (cons :a '(:b))
(или (cons :a (cons :b nil))
) равна list
: (list :a :b)
.
Ответ 5
Когда вы говорите
> (cons 'a 'b)
в общем lisp вы не получаете список, а пунктирную пару: (a . b)
, тогда как результат
> (cons 'a (cons 'b nil))
- пунктирная пара (a . ( b . nil))
.
В первом списке cdr()
этого не является списком, так как он здесь b
, а не nil
, что делает его неправильным. Соответствующие списки должны быть завершены nil
. Поэтому функции более высокого порядка, такие как mapcar()
и друзья, не будут работать, но мы сохраняем cons-cell. Я думаю, разработчики Clojure удалили эту функцию из-за путаницы, которую это могло вызвать.