Pregunta

Necesito definir vars mutuamente dependientes. Con esto quiero decir que un var contiene, por ejemplo, un vector con otro var y viceversa. Esto se ilustra mediante el siguiente código:

(declare a b)
(def a [1 b])
(def b [a 2])

Pero después de cargar este código obtengo esto:

test=> (first a)
1
test=> (second a)
#<Unbound Unbound: #'test/b>
test=> (first b)
[1 #<Unbound Unbound: #'test/b>]
test=> (second b)
2

Claramente, así es como debería funcionar. Entiendo que la impresión de dicha estructura le dará al desbordamiento de pila, pero no necesito imprimirla. ¿Cómo debería hacerlo?

¿Fue útil?

Solución

Puedes hacer lo siguiente:

(declare a b)
(def a [1 #'b])
(def b [#'a 2])

@(a 1)
=> [#'user/a 2]

Tenga en cuenta que #' es una macro lector para referirse a un var.

Sin embargo, todavía no estoy seguro de por qué quieres hacer esto ... tratando de hacer que los vars dependan mutuamente como este me parece un olor de código bastante malo. Es probable que lo que sea que esté tratando de hacer realmente se resuelva mejor con un enfoque diferente.

EDITAR

Con el comentario adicional que indica que el problema está relacionado con tener diferentes tipos de entidades que se refieren entre sí, creo que un mejor enfoque es un mapa con palabras clave, por ejemplo,

(def my-model
  {:a 
      {:name "Entity A" 
       :references [:b]}
   :b 
      {:name "Entity B"
       :references [:a]}}

Otros consejos

Primero, esto huele mucho a un problema XY.

En segundo lugar, las estructuras de datos mutuamente referenciales no se pueden crear sin el estado de mutación. Si esa es la estructura de datos que necesita (y probablemente no lo hace), use el enfoque de estado muy bien diseñado de Clojure. Por ejemplo:

user=> (set! *print-level* 2)  ; this is necessary to stop the infinite print recursion
2
user=> (def a (atom [1]))
#'user/a
user=> (def b (atom [a 2]))
#'user/b
user=> (swap! a conj b)
[1 #<Atom@19ed00d1: #>]
user=> @a
[1 #<Atom@19ed00d1: #>]
user=> @b
[#<Atom@5c6c2308: #> 2]

La evaluación perezosa podría ayudar:

user=> (declare a b)
#'user/b
user=> (def a [1 (lazy-seq b)])
#'user/a
user=> (def b [(lazy-seq a) 2])
#'user/b
user=> (first a)
1
user=> (second b)
2
user=> (second a) ;stack overflow
user=> (first b) ;stack overflow
user=> (take 42 (second a)) ;still overflow as it's infinitely deep
user=> (take 42 (first b)) ;still overflow as it's infinitely deep

Espero que ayude, aunque no puedo ver cómo va a ser útil.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top