Общий 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 удалили эту функцию из-за путаницы, которую это могло вызвать.