2012-02-17 7 views
3

相互に依存する変数を定義する必要があります。これは、1つの変数が別の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 

を、それがどのように動作するかをないthatsの。 このような構造体を印刷するとスタックオーバーフローが発生することは理解できますが、印刷する必要はありません。私はどうすればいいのですか?

答えて

3

あなたは、次の操作を行うことができます:#'はVARを参照するためのリーダーマクロであることを

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

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

注意を。

私はまだあなたがこれをやりたがっている理由はまだわかりません.....このように相互に依存するvarsを作成しようとすると、かなり悪いコードのような感じです。あなたがしようとしていることは、実際には別のアプローチによって最も良く解決されるでしょう。問題は、相互に参照エンティティの種類が異なると関連していることを示す追加のコメントで

EDIT

、私は例えば、より良いアプローチは、キーワードとのマップだと思います

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

はい、私はヴァルスで何かをするべきだと思いました。ありがとう。私がしたいことは次のとおりです。いくつかの種類のエンティティの多対多の関係を(潜在的に)記述する必要があります。これらのタイプとその関係は一定です。私はそれらを互いに参照を持つvarsとして定義したいので、別の型によって参照される型を取得したい場合、 '(first(:references src-type))'のような簡単なことができます。 –

+0

あなたはおそらく正しいでしょう。多分グローバルマップを使用して、単純なキーワードで参照する必要があります。あなたはどう思いますか?それはより良いアプローチでしょうか? –

+1

はい、キーワードを使った大きな地図がうまくいくと思います。すべての単なるデータです。コピーを作成したり、シリアル化したり、テストケースなどのために異なるバージョンを作成することができます。マップを使用すると簡単ですが、ヴァルスを使用しようとすると非常に手早くなります。 – mikera

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 #<[email protected]: #>] 
user=> @a 
[1 #<[email protected]: #>] 
user=> @b 
[#<[email protected]: #> 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 

は、私は有用であることが起こっているのか見ることができないけれども、それは、お役に立てば幸いです。

関連する問題