2010-07-11 5 views
13

(Renuncia - Soy consciente de la importancia de SEQs en Clojure)common lisp cons crea una lista a partir de dos símbolos, clojure cons requiere un seq para contra?

En Common Lisp la función contras se puede utilizar para combinar dos símbolos en una lista:

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

En clojure - se puede solo contras en una secuencia - los contras no se han extendido para trabajar con dos símbolos. Así que hay que escribir:

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

¿Hay un patrón de nivel superior en Clojure que explica esta diferencia entre Common Lisp y Clojure?

+0

¡He estado programando en Clojure un poco y ni siquiera estaba al tanto de esto! Si lo que usted afirma es correcto, esta es una buena pregunta :) –

+0

Tenga en cuenta que normalmente es mejor usar 'conj' que' contra'. Para obtener más detalles, consulte mi respuesta a esta pregunta (y el comentario de cgrand): http://stackoverflow.com/questions/3008411/clojure-seq-cons-vs-list-conj (De hecho, esa respuesta también explica la función de 'contras 'en Clojure en contraste con los tradicionales' contras 'de Lisp hasta cierto punto.) –

+3

Su primer ejemplo no es una lista, es un par. Un par (a. B) es diferente de una lista de dos elementos (ab), que resulta ser el par (a. (B. Nil)) – Zorf

Respuesta

9

En Clojure, a diferencia de los Lisps tradicionales, las listas no son las estructuras de datos principales. Las estructuras de datos pueden implementar la interfaz ISeq, que es otra vista de la estructura de datos que se proporciona, permitiendo que las mismas funciones accedan a elementos en cada una. (Listas ya implementar esto. seq? comprueba si algo implementa ISeq. (seq? '(1 2)), (seq? [1 2])) Clojure simplemente actúa de manera diferente (con razón), en el que cuando cons se utiliza, una secuencia (en realidad es de tipo clojure.lang.Cons) construida de a y (seq b) se devuelve. (a siendo arg arg 1 y b 2) Obviamente, símbolos y no se pueden aplicar no ISeq.

Clojure.org/sequences

Sequences screencast/talk by Rich Hickey sin embargo, tenga en cuenta que rest ha cambiado, y es el comportamiento anterior está ahora en next, y que lazy-cons ha sido reemplazado por lazy-seq y cons.

clojure.lang.RT

2

Cuando dice

> (cons 'a 'b) 

en Common Lisp no te dan una lista, pero un par de puntos: (a . b), mientras que el resultado de

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

es el par de puntos (a . (b . nil)).

En la primera lista, cdr() no es una lista, ya que está aquí b y no nil, lo que la convierte en una lista incorrecta. Las listas adecuadas deben finalizar al nil. Por lo tanto, las funciones de orden superior como mapcar() y sus amigos no funcionarán, pero guardamos una celda cons. Supongo que los diseñadores de Clojure eliminaron esta función debido a la confusión que podría causar.

+1

Se debe tener en cuenta que '(a. (B. Nil)) '_es_ una lista Lisp, comúnmente indicada como' (ab) '. – Svante

5

En Common Lisp CONS crea una denominada célula CONS, que es similar a un disco con dos ranuras: el 'coche' y el 'CDR'.

Puede poner CUALQUIER COSA en esas dos ranuras de una celda de cons.

Las celdas Cons se utilizan para crear listas. Pero uno puede crear todo tipo de estructuras de datos con células cons: árboles, gráficos, varios tipos de listas especializadas, ...

Las implementaciones de Lisp están altamente optimizadas para proporcionar células cons muy eficientes.

3

Una lista Lisp es solo una forma común de usar celdas cons (ver Rainer's description). Es mejor ver que Clojure no tiene células cons (aunque algo similar podría esconderse debajo del capó). El Clojure cons es un nombre inapropiado, en realidad debería llamarse prepend.

3

En Clojure, se prefiere el uso de un vector de dos elementos: [:a :b]. Bajo el capó, esos pequeños vectores se implementan como matrices de Java y son extremadamente simples y rápidos.

Una mano corta para (cons :a '(:b)) (o (cons :a (cons :b nil))) es list: (list :a :b).

Cuestiones relacionadas