2016-12-18 13 views
6

swap! फ़ंक्शन, क्लोजर टूलबॉक्स में सबसे बेवकूफ उपकरण में से एक, instance? जांच करता है। पॉलिमॉर्फिज्म (प्रोटोकॉल) को प्राथमिकता देने के लिए, टाइपिंग जांच के आसपास सशर्त कार्यान्वयन से बचने के लिए प्रोग्रामिंग में हमें बताया जाता है। ऐसा लगता है कि क्लोजरस्क्रिप्ट ISwap प्रोटोकॉल को सीधे परमाणुओं के खिलाफ लागू नहीं करता है और इसके बजाय प्रोटोकॉल पर वापस आने के बाद केवल swap! एपीआई प्रोटोकॉल पर वापस आ रहा है, यह जांचने के बाद कि विषय परमाणु है या नहीं।क्लोजरस्क्रिप्ट परमाणु पूर्ण प्रोटोकॉल को लागू क्यों नहीं करते हैं?

मुझे लगता है कि इस रणनीति का प्रदर्शन कारणों से किया जाना चाहिए क्योंकि परमाणु swap! और कई अन्य परमाणु तरीकों के लिए प्राथमिक उपयोग केस हैं। क्या यह सही है?

मैं वास्तविक प्रोटोकॉल के हिस्से के रूप में एक परमाणु एपीआई को लागू करना पसंद करता था ताकि इस तरह की चीज अनावश्यक हो।

(defn swap! 
    "Atomically swaps the value of atom to be: 
    (apply f current-value-of-atom args). Note that f may be called 
    multiple times, and thus should be free of side effects. Returns 
    the value that was swapped in." 
    ([a f] 
    (if (instance? Atom a) 
     (reset! a (f (.-state a))) 
     (-swap! a f))) 
    ([a f x] 
    (if (instance? Atom a) 
     (reset! a (f (.-state a) x)) 
     (-swap! a f x))) 
    ([a f x y] 
    (if (instance? Atom a) 
     (reset! a (f (.-state a) x y)) 
     (-swap! a f x y))) 
    ([a f x y & more] 
    (if (instance? Atom a) 
     (reset! a (apply f (.-state a) x y more)) 
     (-swap! a f x y more)))) 

उत्तर

2

ऐसा लगता है कि यह संबंधित प्रदर्शन है: http://dev.clojure.org/jira/browse/CLJS-760

एक -reset के साथ एक IAtom प्रोटोकॉल जोड़ें! cljs.core/रीसेट में एटम के लिए विधि और एक तेज रास्ता!

jsperf यहाँ देखें - http://jsperf.com/iatom-adv

नवीनतम क्रोम और फ़ायरफ़ॉक्स संस्करणों पीड़ित ~ 20-30% मंदी। पुराने फ़ायरफ़ॉक्स संस्करण 60-70% तक पीड़ित हैं।

टिकट के नीचे, आईएटॉम को दो प्रोटोकॉल में विभाजित करने का निर्णय लिया गया: आईरसेट और आईएसएपीएपी। लेकिन यह कार्यान्वयन था कि डेविड के साथ चला गया, जो प्रकार की जांच करता है, और मुझे लगता है कि गति को वापस पाने के लिए किया गया था।

दुर्भाग्य से, यह स्पष्ट नहीं है क्यों एटम उस बात के लिए IReset (और ISwap) लागू करने के लिए नहीं किया गया था, और न ही क्यों उन चीजों के बजाय के लिए देखा नहीं थे। और यह स्पष्ट नहीं है कि मूल पैच कैसे काम करता है। यह मूल रूप से reset! के कार्यान्वयन में ले लिया और एक instance जांच के अंतर्गत रखें, और इसके लिए -reset! पथ कहा:

diff --git a/src/cljs/cljs/core.cljs b/src/cljs/cljs/core.cljs 
index 9fed929..c6e41ab 100644 
--- a/src/cljs/cljs/core.cljs 
+++ b/src/cljs/cljs/core.cljs 
@@ -7039,6 +7039,9 @@ reduces them without incurring seq initialization" 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reference Types ;;;;;;;;;;;;;;;; 

+(defprotocol IAtom 
+ (-reset! [o new-value])) 
+ 
(deftype Atom [state meta validator watches] 
    IEquiv 
    (-equiv [o other] (identical? o other)) 
@@ -7088,14 +7091,16 @@ reduces them without incurring seq initialization" 
    "Sets the value of atom to newval without regard for the 
    current value. Returns newval." 
    [a new-value] 
+ (if (instance? Atom a) 
    (let [validate (.-validator a)] 
     (when-not (nil? validate) 
-  (assert (validate new-value) "Validator rejected reference state"))) 
+  (assert (validate new-value) "Validator rejected reference state")) 
     (let [old-value (.-state a)] 
     (set! (.-state a) new-value) 
     (when-not (nil? (.-watches a)) 
-  (-notify-watches a old-value new-value))) 
- new-value) 
+   (-notify-watches a old-value new-value)) 
+  new-value)) 
+ (-reset! a new-value))) 

(defn swap! 
    "Atomically swaps the value of atom to be: 

यह 33692b79a114faf4bedc6d9ab38d25ce6ea4b295 (बहुत करीब या कम से कम कुछ) में प्रतिबद्ध है। और फिर अन्य प्रोटोकॉल परिवर्तन 3e6564a72dc5e175fc65c9767364d05af34e4968 में किया गया:

commit 3e6564a72dc5e175fc65c9767364d05af34e4968 
Author: David Nolen <[email protected]> 
Date: Mon Feb 17 14:46:10 2014 -0500 

    CLJS-760: break apart IAtom protocol into IReset & ISwap 

diff --git a/src/cljs/cljs/core.cljs b/src/cljs/cljs/core.cljs 
index 25858084..e4df4420 100644 
--- a/src/cljs/cljs/core.cljs 
+++ b/src/cljs/cljs/core.cljs 
@@ -7061,9 +7061,12 @@ reduces them without incurring seq initialization" 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reference Types ;;;;;;;;;;;;;;;; 

-(defprotocol IAtom 
+(defprotocol IReset 
    (-reset! [o new-value])) 

+(defprotocol ISwap 
+ (-swap! [o f] [o f a] [o f a b] [o f a b xs])) 
+ 
(deftype Atom [state meta validator watches] 
    IEquiv 
    (-equiv [o other] (identical? o other)) 
@@ -7124,21 +7127,33 @@ reduces them without incurring seq initialization" 
     new-value)) 
    (-reset! a new-value))) 

+;; generic to all refs 
+;; (but currently hard-coded to atom!) 
+(defn deref 
+ [o] 
+ (-deref o)) 
+ 
(defn swap! 
    "Atomically swaps the value of atom to be: 
    (apply f current-value-of-atom args). Note that f may be called 
    multiple times, and thus should be free of side effects. Returns 
    the value that was swapped in." 
    ([a f] 
-  (reset! a (f (.-state a)))) 
+  (if (instance? Atom a) 
+  (reset! a (f (.-state a))) 
+  (-swap! a (deref a)))) 
    ([a f x] 
-  (reset! a (f (.-state a) x))) 
+  (if (instance? Atom a) 
+  (reset! a (f (.-state a) x)) 
+  (-swap! a (f (deref a) x)))) 
    ([a f x y] 
-  (reset! a (f (.-state a) x y))) 
- ([a f x y z] 
-  (reset! a (f (.-state a) x y z))) 
- ([a f x y z & more] 
-  (reset! a (apply f (.-state a) x y z more)))) 
+  (if (instance? Atom a) 
+  (reset! a (f (.-state a) x y)) 
+  (-swap! a (f (deref a) x y)))) 
+ ([a f x y & more] 
+  (if (instance? Atom a) 
+  (reset! a (apply f (.-state a) x y more)) 
+  (-swap! a (f (deref a) x y more))))) 

(defn compare-and-set! 
    "Atomically sets the value of atom to newval if and only if the 
@@ -7149,13 +7164,6 @@ reduces them without incurring seq initialization" 
    (do (reset! a newval) true) 
    false)) 

-;; generic to all refs 
-;; (but currently hard-coded to atom!) 
- 
-(defn deref 
- [o] 
- (-deref o)) 
- 
(defn set-validator! 
    "Sets the validator-fn for an atom. validator-fn must be nil or a 
    side-effect-free fn of one argument, which will be passed the intended 

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

एक बात मैं Clojure/लिपि में प्रतिबद्ध के बारे में पसंद नहीं है कि वे बहुत वर्णनात्मक नहीं हो रहा है। मेरी इच्छा है कि वे उचित पृष्ठभूमि की जानकारी के साथ अधिक कर्नेल की तरह हों ताकि लोगों (जैसे हमारे) यह पता लगाने की कोशिश कर रहे हों कि चीजों को इसके बारे में और अधिक उपयोगी जानकारी कैसे मिली।

संबंधित मुद्दे