Domanda

Ho bisogno di definire Vars reciprocamente dipendenti. Con questo voglio dire che uno var contiene ad esempio un vettore con un altro var e viceversa. Ciò è illustrato dal codice seguente:

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

Ma dopo aver caricato questo codice ottengo questo:

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

chiaramente, quello non è come dovrebbe funzionare. Capisco che la stampa di tale struttura vi darà overflow dello stack, ma non ho bisogno di stamparlo. Come devo fare?

È stato utile?

Soluzione

È possibile effettuare le seguenti operazioni:

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

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

Si noti che #' è una macro lettore di appellarsi a una var.

Non sono ancora del tutto sicuro perché si vuole fare questo però ..... cercando di fare vars reciprocamente dipendenti come questo mi sembra un codice di odore piuttosto male per me. E 'probabile che tutto ciò che si sta cercando di fare sarebbe effettivamente meglio risolto con un approccio diverso.

Modifica

Con il commento in più che indica che il problema è legato ad avere diversi tipi di entità che si riferiscono gli uni agli altri, penso che un approccio migliore è una mappa con le parole chiave, per esempio.

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

Altri suggerimenti

In primo luogo, questo odore molto simile a un problema di XY.

In secondo luogo, le strutture di dati reciprocamente referenziali non può essere creato senza mutazione di stato. Se questo è la struttura di dati necessari (e probabilmente non), quindi utilizzare l'approccio molto ben progettato di clojure a stato. Ad esempio:

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]

Pigro aiuto valutazione potrebbe:

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

Speranza che aiuta, anche se non riesco a vedere come sta andando essere utile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top