2009-11-21 11 views
16

में स्कॉइंग नियमों के बावजूद मैंने क्लोजर का उपयोग किया है, मैंने विस्तार से स्कॉइंग नियमों को नहीं देखा है। जब मैं दस्तावेज पढ़ता हूं तो मैं और अधिक भ्रमित हो रहा हूं। मैंने स्कोपिंग संकल्पों को आजमाने के लिए एक छोटा परीक्षण किया और जटिलता पर चिंतित हूं। क्या कोई क्लोजर का इरादा और विभिन्न नियमों को समझा सकता है?क्लोजर

(def x 1) 

(defn dummy-fn2[] 
    (+ x 1))   

(defn dummy-fn[] 
    (println "entering function: " x) 
     (let [x 100] 
     (println "after let: " x) 
     (let [x (dummy-fn2)] 
      (println "after let and dummy2: " x) 
      (binding [x 100] 
      (println "after binding: " x) 
      (let [x (dummy-fn2)] 
       (println "after binding and dummy2: " x)))))) 

1:2 foo=> (dummy-fn) 
entering function: 1 
after let: 100 
after let and dummy2: 2 
after binding: 2 
after binding and dummy2: 101 
nil 
+3

आदेश प्रलेखन दोहरा, शायद आप का वर्णन कर सकता है कि आप क्या उम्मीद और क्यों यह वास्तव में होता है से अलग है से बचने के लिए । –

उत्तर

14

Clojure प्रतीकों के लिए शाब्दिक गुंजाइशlet और गतिशील गुंजाइशbinding वार्स के लिए जांच clojure के vars प्रलेखन दोनों का उपयोग करता है।

  • "फ़ंक्शन दर्ज करना": अभी तक ठीक कर रहा है! प्रतीक एक्स var को हल करता है और यह var x के "रूट बाध्यकारी" को पकड़ रहा है।
  • "बाद के बाद": एक स्थानीय बाध्यकारी var को कवर किया गया है, प्रतीक x अब 100 नहीं है। बंधन (+ 1 1)
  • "के बाद डमी-fn2 में एक्स, के लिए वर एक्स संदर्भित करता है तो यह जड़ एक्स के बंधन का उपयोग करता है और कहा कि एक से अधिक दिखाई:
  • " चलो और dummy2 के बाद " ": मुश्किल एक! बाध्यकारी गतिशील रूप से var नामित x (जो 1 था) की मूल बाध्यकारी को 100 के साथ बदल दिया, लेकिन स्थानीय प्रतीक x अब var नहीं है, इसलिए आप स्थानीय बाध्यकारी प्राप्त करते हैं।
  • "बंधन और dummy2 के बाद": 100 के साथ की वर एक्स जड़ मूल्य प्रतिस्थापित बंधन और यह है कि एक से अधिक (+ 100 1)
+0

ऐसा लगता है कि बाध्यकारी "नाम x के साथ var" को प्रतिस्थापित करता है, न कि "प्रतीक x जो प्रतीक x हल करता है" यह सही है? –

+0

"नाम x के साथ var" का क्या अर्थ है? –

+0

जो भी var var द्वारा वापस किया जाता है (संकल्प 'एक्स)। –

22

let छाया एक साथ उच्चस्तरीय वार x लौटे स्थानीय xlet कोई वर नहीं बनाता है या अपरिवर्तनीय Var को प्रभावित नहीं करता है; यह कुछ प्रतीक को बांधता है जैसे कि उस प्रतीक के स्थानीय संदर्भ let -bound मान के साथ प्रतिस्थापित किए जाएंगे। let में लक्सिकल स्कोप है, इसलिए इसकी बाइंडिंग केवल let फॉर्म के भीतर दिखाई दे रही है (let के भीतर से फ़ंक्शंस में नहीं)।

binding अस्थायी रूप से (थ्रेड-स्थानीय रूप से) अपूर्ण Var x के मान को बदलता है, यह सब कुछ करता है। यदि let बाध्यकारी जगह पर है, binding यह तय करते समय यह नहीं देखता कि कौन सा मान बदलना है (और let की बाइंडिंग वर्र्स नहीं हैं और वे बदलाव नहीं कर रहे हैं, ताकि 'अच्छी बात हो या यह आपको त्रुटि दे)। और bindinglet मास्क नहीं करेगा। binding में गतिशील गुंजाइश है, इसलिए यह binding फ़ॉर्म के भीतर और binding फ़ॉर्म के भीतर से किसी भी फ़ंक्शन में दिखाई देने वाले अपरिवर्तित वार्स पर प्रभाव डालता है।

सादे पुराने x का मूल्य तक पहुँचना आप लौटा देंगे बाइंडिंग के ढेर के शीर्ष पर है, या तो सबसे नेस्टेड letx की -bound मूल्य (या समारोह परमाटर x कहा जाता है, या कुछ मूल्य x साथ बदल दिया है यदि आप अपने स्वयं के मैक्रो, या अन्य संभावनाओं का उपयोग करते हैं।), और डिफ़ॉल्ट रूप से अपरिवर्तित Var x के वर्तमान मान का उपयोग केवल तभी किया जाता है जब कोई अन्य बाध्यकारी न हो।

यहां तक ​​कि अगर उच्चस्तरीय वार x एक let -bound x के नीचे दब जाता है, तो आप हमेशा उच्चस्तरीय वार @#'x के माध्यम से पहुँच सकते हैं। इस संस्करण का प्रयास करें, हो सकता है इसे और अधिक समझ बनाने होंगे:

(def x 1) 

(defn dummy-fn2[] 
    (println "x from dummy-fn2:" x) 
    (+ x 1)) 

(defn dummy-fn[] 
    (println "entering function:" x) 
    (println "var x:" @#'x) 
    (dummy-fn2) 
    (println "---") 
    (let [x 100] 
    (println "after let:" x) 
    (println "var x:" @#'x) 
    (dummy-fn2) 
    (println "---") 
    (let [x (dummy-fn2)] 
     (println "after let and dummy-fn2:" x) 
     (println "var x:" @#'x) 
     (dummy-fn2) 
     (println "---") 
     (binding [x 888] 
     (println "after binding:" x) 
     (println "var x:" @#'x) 
     (dummy-fn2) 
     (println "---") 
     (let [x (dummy-fn2)] 
      (println "after binding and dummy2:" x) 
      (println "var x:" @#'x) 
      (dummy-fn2) 
      (println "---")))))) 

देता है:

entering function: 1 
var x: 1 
x from dummy-fn2: 1 
--- 
after let: 100 
var x: 1 
x from dummy-fn2: 1 
--- 
x from dummy-fn2: 1 
after let and dummy-fn2: 2 
var x: 1 
x from dummy-fn2: 1 
--- 
after binding: 2 
var x: 888 
x from dummy-fn2: 888 
--- 
x from dummy-fn2: 888 
after binding and dummy2: 889 
var x: 888 
x from dummy-fn2: 888 
--- 
+0

मिल रहा है, मुझे 'IllegalStateException गतिशील रूप से गैर-गतिशील var को बाध्य नहीं कर सकता है। इसे 'बाध्यकारी 'फ़ॉर्म को' लेट 'के साथ या' (def ^: गतिशील x 1) 'के साथ बदलकर हल किया गया है। – dkinzer