2012-11-27 6 views
5

私は、1つのクローズ・ネームスペース内のオブジェクトを作成して破棄し、別のネームスペースをコーディネイトする必要があるという状況があります。しかし、私は最初の名前空間がオブジェクトの破棄時に2番目の名前空間を明示的に呼び出さなければならないことは望ましくありません。Clojureでフックを行う方法

Javaでは、リスナーを使用できます。残念ながら、基礎となるJavaライブラリは、オブジェクトの破棄時にイベントを通知しません。私がEmacs-Lispにいたら、そのトリックを行うフックを使います。

今、私は確信していません。私はRobert Hookeのライブラリhttps://github.com/technomancy/robert-hookeを見つけました。しかし、これはelispの点では欠点に似ています - 私は関数を構成しています。ドキュメントの詳細:

"フックはあなたが制御しない機能を拡張することを意図しています;もしあなたが目的の機能を所有していれば、明らかにその動作を変更する良い方法があります。

悲しいことに、私はそれがとてもわかりません。

もう1つの可能性は、add-watchを使用することですが、これはアルファとしてマークされています。

別の明白な解決策がありませんか?

例を追加しました:

だから、まず名前空間....

(ns scratch-clj.first 
    (:require [scratch-clj.another])) 

(def listf (ref())) 

(defn add-object [] 
    (dosync 
    (ref-set listf (conj 
       @listf (Object.)))) 
    (println listf)) 


(defn remove-object [] 
    (scratch-clj.another/do-something-useful (first @listf)) 
    (dosync 
    (ref-set listf (rest @listf))) 
    (println listf)) 


(add-object) 
(remove-object) 

第二に、名前空間

(ns scratch-clj.another) 


(defn do-something-useful [object] 
    (println "object removed is:" object)) 

ここでの問題は、スクラッチclj.firstは別のものを必要とし、明示しなければならないことです削除イベントをプッシュします。これはちょっと大変ですが、 "もう一つの"名前空間があっても聞きたかったらうまくいきません。

私は最初の機能をフックすることを考えました。

+0

HMMの

おかげで、用語 "破壊" について注意してください。オブジェクトの破壊は、GCがクリーンアップするときにのみ起こると私は信じています。オブジェクトを削除することは、オブジェクトを削除することとは異なりますが、オブジェクトを削除することもできます。 –

答えて

1

は、このソリューションは、あなたの要件に適してますか?

スクラッチclj.first:

(ns scratch-clj.first) 

(def listf (atom [])) 
(def destroy-listeners (atom [])) 
(def add-listeners (atom [])) 

(defn add-destroy-listener [f] 
    (swap! destroy-listeners conj f)) 

(defn add-add-listener [f] 
    (swap! add-listeners conj f)) 

(defn add-object [] 
    (let [o (Object.)] 
    (doseq [f @add-listeners] (f o)) 
    (swap! listf conj o) 
    (println @listf))) 

(defn remove-object [] 
    (doseq [f @destroy-listeners] (f (first @listf))) 
    (swap! listf rest) 
    (println @listf)) 

いくつかのリスナー:

(ns scratch-clj.another 
    (:require [scratch-clj.first :as fst])) 

(defn do-something-useful-on-remove [object] 
    (println "object removed is:" object)) 

(defn do-something-useful-on-add [object] 
    (println "object added is:" object)) 

initはバインド:

(ns scratch-clj.testit 
    (require [scratch-clj.another :as another] 
      [scratch-clj.first :as fst])) 

(defn add-listeners [] 
    (fst/add-destroy-listener another/do-something-useful-on-remove) 
    (fst/add-add-listener another/do-something-useful-on-add)) 

(defn test-it [] 
    (add-listeners) 
    (fst/add-object) 
    (fst/remove-object)) 

テスト:

(test-it) 
=> object added is: #<Object [email protected]> 
    [#<Object [email protected]>] 
    object removed is: #<Object [email protected]> 
    () 
+0

はい、そうだと思います。私も時計でこれを行うことができると思うが、これはもっと一般的であるだけでなく、私にはもう少し自然なようだ。どうもありがとう! –

+0

ようこそ。しかし、それはまだ正しいとマークされていません:( – mobyte

1

あなたが説明しているのはコールバックですね。以下のような

何か:

(defn make-object 
    [destructor-fn] 
    {:destructor destructor-fn :other-data "data"}) 

(defn destroy-object 
    [obj] 
    ((:destructor obj) obj)) 

; somewhere at the calling code... 

user> (defn my-callback [o] (pr [:destroying o])) 
#'user/my-callback 
user> (destroy-object (make-object my-callback)) 
[:destroying {:destructor #<user$my_callback [email protected]>, :other-data "data"}] 
nil 
user> 
+0

これは合理的な考えですが、問題を変えるだけです。今私はmake-object関数にフックできる必要があるので、デストラクタを追加することができます。上記の例を参考にしてください(あなたのコメントの後に追加されます、ごめんなさい!) - オブジェクトの作成と破壊はネームスペース "first"で起きていますが、私のコールバックは同等です。 –

+0

さて、そのようなことを述べて、問題の1つは、clojureがデストラクタを持つオブジェクトのアイデアで本当にうまくいきませんということです。すべてのオブジェクトを(ほとんど)「ダム」のレコードと見なすと、一般的には時間がかかります。あなたのコードから、オブジェクトが破壊されているかどうかを確認したくない場合、listfのコレクションが変更されるたびに何らかのアクションを実行する必要があります。時計はこのための明らかなツールであり、すぐに削除される可能性は低いです。 –

+0

この場合、問題のオブジェクト(私の例のようなもの)はJavaオブジェクトです - 私はJava APIを操作するためにclojureを使用しています。リストから削除すると、オブジェクトは破棄されます。リファレンスウォッチは保証されていますか?それは拒否可能ではない? –

0

ここで、私の最終的なソリューションはmobytesの提案に従っています。もう少し仕事がありますが、 私は将来これが欲しいと思っています。すべてのヘルプ

;; hook system 
(defn make-hook [] 
    (atom [])) 

(defn add-hook [hook func] 
    (do 
    (when-not 
     (some #{func} @hook) 
     (swap! hook conj func)) 
    @hook)) 

(defn remove-hook [hook func] 
    (swap! hook 
     (partial 
      remove #{func}))) 

(defn clear-hook [hook] 
    (reset! hook [])) 

(defn run-hook 
    ([hook] 
     (doseq [func @hook] (func))) 
    ([hook & rest] 
     (doseq [func @hook] (apply func rest)))) 

(defn phils-hook [] 
    (println "Phils hook")) 

(defn phils-hook2 [] 
    (println "Phils hook2")) 


(def test-hook (make-hook)) 
(add-hook test-hook phils-hook) 
(add-hook test-hook phils-hook2) 
(run-hook test-hook) 
(remove-hook test-hook phils-hook) 
(run-hook test-hook) 
関連する問題