2012-11-27 14 views
5

में हुक कैसे करें मेरे पास एक ऐसी स्थिति है जहां मैं एक क्लोजर नेमस्पेस में ऑब्जेक्ट्स बना रहा हूं और नष्ट कर रहा हूं, और एक अन्य नेमस्पेस को समन्वयित करना चाहता हूं। हालांकि मैं नहीं चाहता कि पहले नामस्थान को ऑब्जेक्ट विनाश पर दूसरी बार स्पष्ट रूप से कॉल करना पड़े।क्लोजर

जावा में, मैं श्रोता का उपयोग कर सकता था। दुर्भाग्य से अंतर्निहित जावा पुस्तकालय वस्तु विनाश पर घटनाओं को संकेत नहीं देते हैं। अगर मैं इमाक्स-लिस्प में था, तो मैं चाल का उपयोग करता हूं जो चाल करता है।

अब, क्लोजर में मुझे इतना यकीन नहीं है। मुझे रॉबर्ट हुक लाइब्रेरी https://github.com/technomancy/robert-hooke मिली है। लेकिन यह elisp शर्तों में defadvice की तरह है - मैं कार्यों को लिख रहा हूँ। दस्तावेज़ीकरण पर अधिक कहते हैं:

"हुक उन कार्यों को बढ़ाने के लिए हैं जिनका आप नियंत्रण नहीं करते हैं; यदि आपके पास लक्ष्य कार्य है तो इसके व्यवहार को बदलने के लिए स्पष्ट रूप से बेहतर तरीके हैं।"

अफसोस की बात है, मुझे यह इतना स्पष्ट नहीं मिल रहा है।

एक और संभावना एड-घड़ी का उपयोग करना होगा, लेकिन इसे अल्फा के रूप में चिह्नित किया गया है।

क्या मुझे एक और स्पष्ट समाधान याद आ रहा है?

उदाहरण जोड़ा गया:

तो सबसे पहले नाम स्थान ....

(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

हम्म के लिए धन्यवाद, शब्द "विनाश" के बारे में सावधान रहना होगा। मेरा मानना ​​है कि ऑब्जेक्ट विनाश केवल तब होता है जब जीसी साफ हो जाता है। वस्तुओं को नष्ट करने के लिए वस्तुओं को हटाने के लिए अलग है, हालांकि कोई दूसरा कारण बन सकता है। –

उत्तर

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

यह एक उचित विचार है, लेकिन यह सिर्फ समस्या को बदल देता है। अब मुझे अपने मेक-ऑब्जेक्ट फ़ंक्शन में हुक करने में सक्षम होना चाहिए, इसलिए मैं एक विनाशक जोड़ सकता हूं। उपरोक्त उदाहरण लें (आपकी टिप्पणी के बाद जोड़ा गया, क्षमा करें!) - ऑब्जेक्ट सृजन और विनाश नामस्थान "पहले" में हो रहा है जबकि मेरे कॉलबैक समतुल्य कहीं और है। –

+0

ठीक है, इस तरह कहा गया है, समस्याओं में से एक यह है कि क्लोजर वास्तव में विनाशकों वाले वस्तुओं के विचार के साथ अच्छी तरह से नहीं खेलता है। यदि आप अपने सभी ऑब्जेक्ट्स को "गूंगा" रिकॉर्ड के रूप में देखते हैं, तो आमतौर पर आपके पास एक अच्छा समय होगा। आपके कोड से आप यह नहीं देखना चाहते हैं कि ऑब्जेक्ट नष्ट हो गया है, आप किसी भी प्रकार की कार्रवाई करना चाहते हैं जब भी सूची में संग्रह संशोधित किया जाता है। घड़ियां इसके लिए स्पष्ट उपकरण हैं और उन्हें जल्द ही किसी भी समय हटाया जाने की संभावना नहीं है। –

+0

इस मामले में, प्रश्न में वस्तुएं (जैसे कि मेरे उदाहरण में) जावा ऑब्जेक्ट्स हैं - मैं जावा एपीआई में हेरफेर करने के लिए क्लोजर का उपयोग कर रहा हूं। एक बार सूची से हटा दिए जाने पर, वस्तुओं को नष्ट कर दिया जाएगा। एक संदर्भ घड़ी को बुलाया जाने की गारंटी है? यह vetoable नहीं है? –

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)