3

相互に依存する変数を定義する必要があります。これは、たとえば、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

明らかに、それはどのように機能するべきではありません。このような構造を印刷するとスタックオーバーフローが発生することは理解していますが、印刷する必要はありません。どうすればいいですか?

4

3 に答える 3

3

次のことができます。

(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]}}
于 2012-02-17T06:52:04.957 に答える
1

まず、これは XY 問題の匂いがします。

第 2 に、相互参照データ構造は、状態を変更しないと作成できません。それが必要なデータ構造である場合 (そしておそらく必要ない場合)、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]
于 2012-02-17T08:13:07.913 に答える
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

役立つことを願っていますが、どのように役立つかはわかりません。

于 2012-02-21T00:43:15.547 に答える