7

मैं क्लोजर का उपयोग कर रहा हूं और मुझे एक छोटा सिमुलेशन चलाने की जरूरत है। मेरे पास लम्बाई का वेक्टर है (एन आमतौर पर 10 और 100 के बीच होता है) जिसमें मूल्य होते हैं। प्रत्येक सिमुलेशन दौर (शायद 1000 राउंड एक साथ) पर, वेक्टर में मानों में से एक को यादृच्छिक रूप से अपडेट किया जाता है। मुझे लगता है कि मैं जावा सरणी का उपयोग करके और एसेट विधि को कॉल करके ऐसा कर सकता हूं, लेकिन यह कार्यात्मक प्रोग्रामिंग/अपरिवर्तनीय मुहावरे को तोड़ देगा।क्लोजर में अपरिवर्तनीय डेटा के साथ संख्यात्मक सिमुलेशन कैसे करें?

क्या ऐसा करने के लिए कोई और अधिक कार्यात्मक तरीका है, या क्या मुझे जावा सरणी के साथ जाना चाहिए?

उत्तर

6
(defn run-sim [arr num-iters update-fn] 
(if (zero? num-iters) 
    arr 
    (let [i (rand-int (count arr)) 
     x (update-fn)] 
    (println "setting arr[" i "] to" x) 
    (recur (assoc arr i x) (dec num-iters) update-fn)))) 

user> (run-sim [1 2 3 4 5 6 7 8 9 10] 10 #(rand-int 1000)) 
setting arr[ 8 ] to 167 
setting arr[ 4 ] to 977 
setting arr[ 5 ] to 810 
setting arr[ 5 ] to 165 
setting arr[ 3 ] to 486 
setting arr[ 1 ] to 382 
setting arr[ 4 ] to 792 
setting arr[ 8 ] to 478 
setting arr[ 4 ] to 144 
setting arr[ 7 ] to 416 
[1 382 3 486 144 165 7 416 478 10] 

यदि आपको इसकी आवश्यकता हो तो जावा सरणी का उपयोग करने में कोई शर्म की बात नहीं है। विशेष रूप से यदि आपको तेजी से जाने की आवश्यकता है। सरणी-उत्परिवर्तन को अपने फ़ंक्शन के अंदर सीमित करें (इनपुट सरणी क्लोन करें और उस पर काम करें) और कोई भी बुद्धिमान नहीं होगा।

+0

धन्यवाद! यह समस्या को हल करने के लिए एक अच्छा तरीका लगता है। –

1

ऐसा नहीं है कि क्लोजर आपको मूल्यों को बदलने नहीं देगा, यह थोड़ा और बोझिल है।

(def vec-ref (ref my-vector)) 

(dosync (set! vec-ref (assoc my-vector index value)) 

बदले गए वेक्टर में मूल्यों को देखने के लिए, @ vec-ref का उपयोग करें।

विवरण में बंद हो सकता है - दुर्भाग्यवश, मैं एक आरईपीएल के पास नहीं हूं। लेकिन यह आपको शुरू करना चाहिए।

+0

धन्यवाद, मैं समस्या को हल करने के इस तरीके की भी जांच करूंगा। –

2

पहले एक फ़ंक्शन को परिभाषित करने दें जो एक नए मूल्य के साथ वेक्टर में यादृच्छिक अनुक्रमणिका अद्यतन करता है। ध्यान दें कि मूल सदिश, बजाय एक नया वेक्टर (अद्यतन मूल्य के साथ) नहीं बदला है लौटा दिया जाता है:

(defn f [xs] 
    (let [r (java.util.Random.) 
     i (.nextInt r (count xs)) 
     b (.nextBoolean r)] 
    (assoc xs i ((if b inc dec) (xs i))))) 

यह समारोह एक सूचकांक चुनता है और फिर इसे या तो बढ़ जाती है या 1. आप से है कि सूचकांक में मूल्य कम हो जाती है निश्चित रूप से इस कार्य को अपनी जरूरतों में बदलना चाहिए।

user=> ((apply comp (repeat 1000 f)) [0 0 0 0 0 0 0]) 
[7 -4 7 6 10 0 -6] 
+0

उत्तर के लिए धन्यवाद, यह रचना-दृष्टिकोण भी दिलचस्प लग रहा है। –

5

ब्रायन की जवाब देने के लिए जोड़ा जा रहा है: आप और अधिक गति की जरूरत है, तो आप भी यात्रियों का सहारा कर सकते हैं

तो यह अपने आप के साथ इस समारोह की रचना करने के रूप में कई बार आप अनुकरण चलाना चाहते हैं एक साधारण मामला है ।

(defn run-sim 
    [vektor num-iters update-fn] 
    (loop [vektor (transient vektor) 
     num-iters (int num-iters)] 
    (if (zero? num-iters) 
     (persistent! vektor) 
     (let [i (rand-int (count vektor)) 
      x (update-fn)] 
     (recur (assoc! vektor i x) (dec num-iters)))))) 
+0

धन्यवाद! मुझे उस क्षणिक सामान में खोदना होगा, गति हमेशा अच्छी होती है! –

+1

ट्रांजिस्टर आसान हैं: शुरुआत में कॉल (क्षणिक चीज़)। एक जोड़ें ! संचालन के लिए, उदाहरण के लिए। assoc !, dissoc! आदि लौटने पर कॉल (लगातार! क्षणिक चीज) कॉल करें। हालांकि, आपको अपने फ़ंक्शन के बाहर ट्रांजिस्टर को रिसाव नहीं करना चाहिए। – kotarak

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