相互に依存する変数の定義
-
27-10-2019 - |
質問
相互に依存するVARを定義する必要があります。これにより、1つの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
明らかに、それはそれがどのように機能するかではありません。そのような構造を印刷するとスタックオーバーフローが得られることを理解していますが、印刷する必要はありません。どうすればいいですか?
解決
以下を行うことができます。
(declare a b)
(def a [1 #'b])
(def b [#'a 2])
@(a 1)
=> [#'user/a 2]
ご了承ください #'
varを参照するためのリーダーマクロです。
なぜあなたがこれをやりたいのか、私はまだよくわかりません.....このように相互に依存しているVARをかなり悪いコードの匂いのように思われます。あなたがやろうとしていることは、実際には別のアプローチによって最もよく解決される可能性があります。
編集
問題はさまざまなタイプのエンティティを互いに参照することに関連していると述べている追加のコメントで、より良いアプローチはキーワードを含むマップだと思います。
(def my-model
{:a
{:name "Entity A"
:references [:b]}
:b
{:name "Entity B"
:references [:a]}}
他のヒント
まず、これは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]
怠zyな評価が役立つかもしれません:
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
それが役立つことを願っていますが、それがどのように役立つかはわかりません。
所属していません StackOverflow