मेरे पास एक परमाणु है जो वर्तमान और ऐतिहासिक घटना मायने रखता है।

(def buckets (atom (list)))

यह 20 खाली मूल्यों के रूप में शुरू होता है।

(reset! buckets (apply list (repeat 20 0)))

=> (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

प्रत्येक घटना के लिए सिर की बाल्टी बढ़ जाती है।

(defn- inc-bucket [buckets]
  (conj (rest buckets) (inc (first buckets))))

(defn event-happened [] (swap! buckets inc-bucket))

=> (event-happened)
(1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

यह एक दूसरे के लिए एक बार गिना जाता है कि वह एक इतिहास है।

(defn- shift-buckets [buckets]
  (conj (drop-last buckets) 0))

(once-a-second-run (swap! buckets shift-bucket))

=>  (swap! buckets shift-bucket)
(0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

यह सब ज्यादातर समय ठीक रहता है। लेकिन कभी-कभी (सप्ताह में एक बार कहते हैं) मुझे लगता है कि buckets की लंबाई 5 पर रीसेट की गई है, न कि सही मान (इस उदाहरण में 20)।

=> @buckets
(0 1 0 0 0)

इन कार्यों में एकमात्र स्थान buckets का उपयोग किया जाता है और मान देखने के लिए deref के साथ।

कुछ गलत हो गया, और मैं कैसे या कहाँ काम नहीं कर सकता। एकमात्र स्थान buckets संशोधित है, दोनों swap! के ऊपर है और जैसा कि मुझे लगता है कि उनका सही उपयोग किया जा रहा है। कोई विचार?

1
Joe 21 नवम्बर 2015, 22:05

2 जवाब

सबसे बढ़िया उत्तर

मुझे जवाब मिल गया। परमाणुओं में आलस्य और अस्वाभाविक अपवाद। कोई जादू नहीं है।

user=> (reset! buckets (apply list (repeat 20 0)))
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
user=> (dotimes [_ 99999] (swap! buckets shift-buckets))
nil
user=> @buckets

StackOverflowError   clojure.core/map/fn--4557 (core.clj:2627)

user=> (type @buckets)
clojure.lang.Cons

यह लॉग में दिखाया गया था, लेकिन मैंने इसे नहीं देखा था (वहाँ बहुत कुछ चल रहा है)। लेकिन यहाँ पागल बात है:

user=> @buckets ; again
(0 0)

मुझे नहीं पता कि यह उस मूल्य को क्यों देगा। ऐसा नहीं है क्योंकि एक बुरा कोशिका का एक सिर और एक पूंछ होती है, क्योंकि उत्पादन में (0 0 0 0 0) था। किसी भी तरह से यह अपरिभाषित व्यवहार है, इसलिए इसका कोई मतलब नहीं है।

इसे ठीक करने के लिए, सूची को हर बार महसूस किया जाना चाहिए।

user=> (defn- shift-buckets-nonlazy [buckets]
  #_=>   (apply list (conj (drop-last buckets) 0)))
#'user/shift-buckets-nonlazy
user=> (reset! buckets (apply list (repeat 20 0)))
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
user=> (dotimes [_ 999999] (swap! buckets shift-buckets-nonlazy))
nil
user=> (type @buckets)
clojure.lang.PersistentList
user=> @buckets
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
3
Joe 22 नवम्बर 2015, 11:38

समस्या को आपके द्वारा पोस्ट नहीं किए गए कोड में होना चाहिए: आपके प्रश्न में सब कुछ पूरी तरह से सही लगता है, और आपके द्वारा वर्णित व्यवहार का कारण नहीं बन सकता है।

0
amalloy 21 नवम्बर 2015, 19:47