2013-06-18 3 views
5

गूगल कॉमन लिस्प स्टाइल गाइड कहना Avoid modifying local variables, try rebinding insteadGoogle Common Lisp Style Guide से: "स्थानीय चर को संशोधित करने से बचें, इसके बजाए रीबंडिंग करने का प्रयास करें" अर्थ?

इसका क्या मतलब है? उस वाक्य में रीबाइंडिंग का मतलब क्या है?

+1

रीबंडिंग, सबसे अधिक संभावना है, जैसा कि पिछले नाम को नए नाम के साथ मास्किंग करना है, उदाहरण के लिए, '(चलो ((ए 1)) (चलो ((ए 2)) ...)) –

+1

यह एक गूंगा दिशानिर्देश है । एक सिर जाओ और आप चाहते हैं कि स्थानीय चर को संशोधित करें। ध्यान दें कि 'लूप' स्थानीय चर को संशोधित करता है। '(10 से नीचे के लिए लूप ...) ',' i' का पुनर्वितरण नहीं होता है; 'i' का एक उदाहरण चरणबद्ध है, इसलिए" स्थानीय चर को संशोधित करने से बचें "" लूप' से बचें "के बराबर है। और इस प्रकार, "reductio विज्ञापन धर्म" अनुमान के नियम से, हम इस दिशानिर्देश को गलत साबित करते हैं। – Kaz

+0

जैसा कि आप शायद जानते हैं, सामान्य लिस्प मानक यह निर्दिष्ट नहीं करता है कि 'LOOP' एक नया चर बांधता है या मौजूदा को बदलता है या नहीं। और मैं इसे एक सख्त नियम के बजाय एक सामान्य दिशानिर्देश के रूप में समझता हूं जिसे तोड़ा नहीं जाना चाहिए। –

उत्तर

9

इसका मतलब है कि आप नए चर के बजाय बनाना चाहिए मान बदलने: एक ही समारोह do मैक्रो (जो, वैसे, भी rebinding, संशोधित नहीं, कम से कम इस योजना में उपयोग करता है) का उपयोग करते हुए लिखा जा सकता है पुराने लोगों का एक एक नया बाध्यकारी बनाना चाहिए

(defun foo (x) 
    (when (minusp x) 
    (setq x (- x))) 
    do something with x) 

इसके बजाय, और प्रयोग के बजाय कि एक: उदाहरण के लिए, निम्न कोड डालें

(defun foo (x) 
    (let ((xabs (if (minusp x) 
        (- x) 
        x))) 
    do something with xabs) 

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

अब आप पूछ सकते हैं कि यह इतना महत्वपूर्ण क्यों है? खैर, कुछ लोगों के लिए दूसरों के मुकाबले इसकी मजबूत प्राथमिकता है। खासकर जो लोग लिस्प के कार्यात्मक पहलू पर जोर देना पसंद करते हैं, वे इस शैली की वकालत करेंगे। हालांकि, वरीयता के बावजूद, यह हमेशा इस तथ्य पर भरोसा करने में सक्षम होना बहुत उपयोगी हो सकता है कि चर बदलता नहीं है। एक उदाहरण है जहाँ इस महत्वपूर्ण हो सकता है:

(defun foo (x) 
    (let ((function #'(lambda() (format t "the value of x is ~a~%" x)))) 
    (when (minusp x) 
     (setq x (- x))) 
    (other-function x) 
    function)) 

फिर, FOO की वापसी मान एक समारोह जब x का मूल्य प्रिंट के साथ कहा जाता है। लेकिन, मूल्य x के बाद समारोह में, पूर्ण मूल्य होगा। यह कार्य बहुत बड़ा हो सकता है अगर फ़ंक्शन बड़ा और जटिल हो।

+0

+1। यह भी ध्यान रखना दिलचस्प है कि '(चलो ((x (abs x))) ...)' भी काम करेगा - इतना नहीं 'abs' फ़ंक्शन, लेकिन तथ्य यह है कि एक ही परिवर्तनीय नाम का उपयोग किया जा सकता है नया चर –

+3

एक संशोधित मूल्य का जिक्र करने वाला बंद मुझे याद दिलाता है कि जावास्क्रिप्ट में, बटनों की एक सरणी पर पुनरावृत्ति करने के लिए फॉर-लूप का उपयोग करके और ऑनक्लिक इंडेक्स को संदर्भित करने वाले ऑनक्लिक हैंडलर को जोड़ने का एक बुरा विचार है –

+3

@LeCurious बंद-ओवर-पुनरावृत्ति - सामान्य लिस्प में भी व्यावहारिक समस्या आती है, खासकर [लूप मैक्रो] (http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm) के साथ। उदाहरण के लिए, देखें [लूप मैक्रो और क्लोजर के साथ अप्रत्याशित व्यवहार] (http://stackoverflow.com/questions/15714537/unexpected-behavior-with-loop-macro-and-closures), जो इस सटीक व्यवहार को प्रदर्शित करता है। –

4

मुझे आम लिस्प में यह कैसे करने के लिए सामान्य लिस्प को पर्याप्त जानकारी नहीं है, इसलिए मैं नीचे दिए गए उदाहरण के लिए योजना का उपयोग कर रहा हूं। मान लीजिए कि आप किसी संख्या के फैक्टोरियल को वापस करने के लिए एक फ़ंक्शन लिख रहे हैं। यहाँ है कि कार्य करने के लिए एक "स्थानीय चर को संशोधित" दृष्टिकोण (आप अपने खुद के while मैक्रो निर्धारित करना होगा, लेकिन यह मुश्किल नहीं है) है:

(define (factorial n) 
    (define result 1) 
    (while (> n 0) 
    (set! result (* result n)) 
    (set! n (- n 1))) 
    result) 

यहाँ कि समारोह के लिए एक "स्थानीय चर rebind" दृष्टिकोण है:

(define (factorial n) 
    (let loop ((n n) 
      (result 1)) 
    (if (zero? n) 
     result 
     (loop (- n 1) (* result n))))) 

इस मामले में, loop को प्रत्येक बार के साथ पुनर्निर्मित करने के लिए नए मानों के साथ बुलाया जाता है।

(define (factorial n) 
    (do ((n n (- n 1)) 
     (result 1 (* result n))) 
     ((zero? n) result))) 
संबंधित मुद्दे