定义相互依赖的变量

发布于 2025-01-06 06:23:47 字数 409 浏览 4 评论 0原文

我需要定义相互依赖的变量。我的意思是一个 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

显然,这不是它应该如何工作的。 我知道打印这样的结构会导致堆栈溢出,但我不需要打印它。我该怎么做呢?

I need to define mutually-dependent vars. By this I mean that one var contains e.g. a vector with another var and vice versa. This is illustrated by the following code:

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

But after loading this code I get this:

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

clearly, thats not how it should work.
I understand that printing such structure will give stack overflow, but I don't need to print it. How should I do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不美如何 2025-01-13 06:23:47

您可以执行以下操作:

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

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

请注意,#' 是用于引用 var 的读取器宏。

我仍然不太确定你为什么要这样做......试图让变量像这样相互依赖对我来说似乎是一个非常糟糕的代码味道。无论您尝试做什么,实际上都可以通过不同的方法得到最好的解决。

编辑

额外的评论指出问题与不同类型的实体相互引用有关,我认为更好的方法是带有关键字的地图,例如

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

You can do the following:

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

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

Note that #' is a reader macro for referring to a var.

I'm still not quite sure why you want to do this though..... trying to make vars mutually dependent like this seems like a pretty bad code smell to me. It's likely that whatever you are trying to do would actually be best solved by a different approach.

EDIT

With the extra comment stating that the problem is related to having different types of entities referring to each other, I think a better approach is a map with keywords, e.g.

(def my-model
  {:a 
      {:name "Entity A" 
       :references [:b]}
   :b 
      {:name "Entity B"
       :references [:a]}}
情何以堪。 2025-01-13 06:23:47

首先,这听起来很像 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]

First, this smells very much like an XY problem.

Second, mutually referential data structures cannot be created without mutating state. If that's the data structure you need (and you probably don't), then use clojure's very well designed approach to state. For example:

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]
看轻我的陪伴 2025-01-13 06:23:47

惰性评估可能会有所帮助:

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

希望它有帮助,尽管我看不出它有什么用处。

Lazy evaluation might help:

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

Hope it helps, though I can't see how it's going to be useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文