2011-01-02 8 views
3

私はかなり大きなツリーを形成するClojureハッシュマップ(STM refを介してアクセス)のさまざまな部分を変更し、一部の登録済みリスナーを呼びたい部分の変更を見たいと思います。 「add-watch」は参照全体でしか機能しないと理解しているので、どのようにしてこれをクロージャーで行うことができますか?変更をClojureツリーのサブセット(ハッシュマップ)で確認するにはどうすればよいですか?

答えて

1

私はツリー全体を見て、get-inでサブセットをチェックします。同じサブツリーを使用してサブツリーが変更されたかどうかを素早くテストできます。前の状態に対してテストする。私は確信して、私は非常に頻繁にウォッチャーを使用していない

(defn change-tester [tree path] 
    (let [orig (get-in tree path)] 
    (fn [tree] 
     (not (identical? (get-in tree path) orig))))) 

のようなものは、私は構文を知らないが、あなたは何とか上記の機能を付けることができます。

2

Clojureマップは不変なので、概念的な観点からは、ツリーの単一の部分を変更することは実際にはありません。

しかし私は良いオプションのカップルを見ることができます:

  • をツリー全体に時計を追加しますが、興味のある特定の部分が変更されたかどうかをテストします。これは非常に迅速かつ簡単にテストする必要があります(ツリーの正しい部分を検索するために "get-in"を使用)
  • ヘルパー関数
+0

申し訳ありませんが、私は、ツリーが参照 – Zubair

1

Clojureマップは、スレッドセーフであることを意味しています。これは良いことです。 'assoc'などで変更すると、変更された値が存在する新しいコピーが作成されます。 (完全なコピーは作成されていませんが、コピーを作成するには効率的な手法が採用されています)。

おそらく、あなたが望むことを実行する最良の方法は、独自のデータ構造を作成することです。あなたはJavaのように変更可能なHashMapを要求していますが、Clojureマップは要求していません。

'put'と 'putAll'メソッドをオーバーライドする既存のJava HashMapの周りにラッパーを作成して、変更内容を検出できるようにすることができます。 HashMap内にHashMapがある場合は、サブHashMapを新しいタイプにして、どのレベルでも変更を検出できるようにします。

「WatchfulHashMap」のように呼び出すこともできます。したがって、どこでもあなたのアプリ内から、それの単一のインスタンスが変更すること

(def m (ref (WatchfulHashMap.))) 

:次に、あなたのようなこの新しいHashMapのインスタンスを作成することになるでしょう。

+0

であるときに部分的な変更を監視する方法を指していましたので、clojure add-watchは変更可能な構造でしか機能しません。 – Zubair

+0

いいえ、それらはrefsで動作します。 'add-watch'アプローチを使用すると、構造内のすべてのノードに「追加時計」を追加するか、構造の古い状態と新しい状態を区別する1つの時計を余儀なくされるようです。 – Psyllo

関連する問題