我需要定义相互依赖的变量。我的意思是,一个var包含例如另一个var的向量,反之亦然。这由以下代码说明:
(declare a b)
(def a [1 b])
(def b [a 2])
但是在加载这段代码后我得到了这个:
test=> (first a)
1
test=> (second a)
#<Unbound Unbound: #'test/b>
test=> (first b)
[1 #<Unbound Unbound: #'test/b>]
test=> (second b)
2
显然,那不是它应该如何运作。
我知道打印这样的结构会给堆栈溢出,但我不需要打印它。我该怎么办?
答案 0 :(得分:3)
您可以执行以下操作:
(declare a b)
(def a [1 #'b])
(def b [#'a 2])
@(a 1)
=> [#'user/a 2]
请注意,#'
是一个读取器宏,用于引用var。
我仍然不太确定你为什么要这样做尽管.....试图让vars相互依赖,这对我来说似乎是一个非常糟糕的代码味道。无论你想要做什么,实际上最好通过不同的方法来解决。
修改强>
由于额外的评论声明问题与不同类型的实体相互引用有关,我认为更好的方法是使用关键字的地图,例如。
(def my-model
{:a
{:name "Entity A"
:references [:b]}
:b
{:name "Entity B"
:references [:a]}}
答案 1 :(得分:1)
首先,这非常像XY问题。
其次,如果没有变异状态,就无法创建相互参照的数据结构。如果这是你需要的数据结构(你可能没有),那么使用clojure设计得非常好的状态。例如:
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]
答案 2 :(得分:0)
懒惰评估可能有所帮助:
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
希望它有所帮助,虽然我看不出它会如何有用。