2010-09-12 24 views
22

Ignorando interoperabilidad nativa y transitorios, ¿es posible crear cualquier estructura de datos en Clojure que contenga referencias circulares directas?¿Es posible crear referencias circulares en Clojure?

Parecería que las estructuras de datos inmutables solo pueden contener referencias a versiones anteriores de ellos mismos. ¿Hay alguna API Clojure que pueda crear una nueva estructura de datos que tenga una referencia a sí misma?

Scheme tiene la forma letrec que permite crear estructuras mutuamente recursivas, pero, hasta donde puedo decir, Clojure no tiene nada similar.

Esta pregunta está relacionada con la transferencia de Clojure a iOS, que no tiene recolección de basura, pero tiene recuento de referencias.

+0

Aquí hay una pregunta SO muy relacionada: [¿Cómo crear una función recursiva anónima que genere lazy-seq en Clojure?] (Http://stackoverflow.com/questions/3373157/how-to-create-a-lazy- seq-generating-anonymous-recursive-function-in-clojure). Ver mi respuesta para una serie de enfoques posibles. Una de ellas es a través de una macro 'letrec' de algún tipo; consulte [este Gist] (http://gist.github.com/486880) para mi versión (que funciona como' letrec' de Scheme). –

+0

Gracias por todas las respuestas. Parece que necesitaré GC completo para manejar Clojure y estoy experimentando con Gambit Scheme como el objetivo de traducción. –

+0

Puede que le interese [Propuesta de intercambio de pila] (http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2 "revisión de código"). Está casi listo para comenzar la versión beta, solo necesita algunos más. – greatwolf

Respuesta

14

Puede crear una referencia circular muy fácilmente poniendo algún tipo de referencia dentro de una estructura de datos, y luego actualizando la referencia para volver a la estructura general.

Un ejemplo trivial:

(def a [(atom nil)]) 

(reset! (first a) a) 

Esto creará una lista con un elemento, que es un átomo que señala hacia atrás en la lista.

+0

Gracias por la respuesta. Solo usaría un tipo de ref como un objeto de nivel superior, así que nunca lo consideré. –

+0

es una var que apunta a una lista que apunta a un átomo que hace referencia a un var –

+1

@Arther - técnicamente es una var que apunta a un vector que contiene un átomo que apunta al vector. es decir, la var en sí no está en el bucle circular. – mikera

8

En Clojure la mayoría de las estructuras de datos circulares atravesarán explícitamente un tipo de ref de algún tipo (por ejemplo, átomo).

Sin embargo, puede crear una secuencia circular (que es un poco un oxímoron):

(let [a (atom nil)] (reset! a (lazy-seq (cons 1 @a)))) 

Y como Clojure 1.2 con DEFTYPE puede crear otros tipos de datos que pueden introducir la circularidad sin utilizar explícitamente (del código de usuario por lo menos) cualquier tipo de tipo de ref.

Cuestiones relacionadas