2012-09-29 13 views
6

मैं प्रैक्टिकल कॉमन लिस्प के माध्यम से पढ़ रहा/काम कर रहा हूं। मैं लिस्प में एक टेस्ट फ्रेमवर्क बनाने के बारे में अध्याय पर हूं।यह लिस्प मैक्रो पूरे काम के रूप में क्यों करता है, भले ही प्रत्येक टुकड़ा काम न करे?

मैं समारोह है "परीक्षण +" के रूप में नीचे लागू किया है, और यह काम करता है:

(defun test-+() 
    (check 
    (= (+ 1 2) 3) 
    (= (+ 5 6) 11) 
    (= (+ -1 -6) -7))) 

, याद रखें कि मैंने कहा, यह काम करता है, जिसके कारण क्या इस प्रकार है तो चौंकाने है ....

यहाँ कुछ कोड है कि "परीक्षण +" को संदर्भित करता है:, मैं क्या कर रहा हूँ करने के लिए स्लाइम उपयोग कर रहा है इन वृहद विस्तार, चरण दर चरण

(defmacro check (&body forms) 
    `(combine-results 
    ,@(loop for f in forms collect `(report-result ,f ',f)))) 

(defmacro combine-results (&body forms) 
    (with-gensyms (result) 
    `(let ((,result t)) 
     ,@(loop for f in forms collect `(unless ,f (setf ,result nil))) 
     ,result))) 

(defmacro with-gensyms ((&rest names) &body body) 
    `(let ,(loop for n in names collect `(,n (gensym))) 
    ,@body)) 

(defun report-result (value form) 
    (format t "~:[FAIL~;pass~] ... ~a~%" value form) 
    value) 

अब (ग का उपयोग कर trl-c आरईटी, जो मैक्रोएक्सपैंड -1 में मैप किया गया है)।

तो, की कॉल "जाँच" "परीक्षण +" यह करने के लिए फैलता है:

(COMBINE-RESULTS 
    (REPORT-RESULT (= (+ 1 2) 3) '(= (+ 1 2) 3)) 
    (REPORT-RESULT (= (+ 5 6) 11) '(= (+ 5 6) 11)) 
    (REPORT-RESULT (= (+ -1 -6) -7) '(= (+ -1 -6) -7))) 

और फिर कि इस के वृहद विस्तार होने:

(LET ((#:G2867 T)) 
    (UNLESS (REPORT-RESULT (= (+ 1 2) 3) '(= (+ 1 2) 3)) (SETF #:G2867 NIL)) 
    (UNLESS (REPORT-RESULT (= (+ 5 6) 11) '(= (+ 5 6) 11)) (SETF #:G2867 NIL)) 
    (UNLESS (REPORT-RESULT (= (+ -1 -6) -7) '(= (+ -1 -6) -7)) 
    (SETF #:G2867 NIL)) 
    #:G2867) 

और यह है कोड, सीधे इस वाक्य से ऊपर है, जो काम नहीं करता है। अब G2867 [प्रकार की स्थिति अबाध-चर]

:

अनबाउंड चर: # अगर मैं कि आरईपीएल में, मैं निम्नलिखित त्रुटि (मैं Clozure कॉमन लिस्प उपयोग कर रहा हूँ) मिल पेस्ट , अगर मैं वही कोड लेता हूं, तो gensym को एक चर नाम के साथ बदलें "x", यह ठीक काम करता है।

  1. "परीक्षण +" मैक्रो, जो यह सब कहता है, ठीक काम करता है:

    तो, हम निम्नलिखित आश्चर्य की व्याख्या कर सकते हैं।

  2. "गठबंधन-परिणाम" मैक्रो का मैक्रो-विस्तार रन नहीं करता है।

  3. अगर मैं की "गठबंधन-परिणाम" वृहद विस्तार से gensym निकालते हैं तो वह काम करता है।

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

धन्यवाद।

उत्तर

11

कोड मुद्रित होने और वापस पढ़ने के बाद, कोड अब एक ही कोड नहीं है। विशेष रूप से, मुद्रित प्रतिनिधित्व में #:G2867 के दो उदाहरण दो अलग-अलग प्रतीकों (हालांकि समान नाम साझा करने के बावजूद) के रूप में पढ़े जाएंगे, जबकि वे मूल आंतरिक प्रतिनिधित्व में समान होना चाहिए।

मैक्रो-विस्तारित कोड के मुद्रित प्रतिनिधित्व में पहचान को संरक्षित करने के लिए *PRINT-CIRCLE*T पर सेट करने का प्रयास करें।

11

GENSYM अनियंत्रित प्रतीकों का निर्माण करता है। जब मैक्रो सामान्य रूप से चलता है, यह कोई समस्या नहीं है, क्योंकि अभिव्यक्ति के दौरान एक ही अनियंत्रित प्रतीक को प्रतिस्थापित किया जा रहा है।

लेकिन जब आप अभिव्यक्ति को प्रतिलिपि में कॉपी और पेस्ट करते हैं, तो ऐसा नहीं होता है। #: पाठक को एक अनियंत्रित प्रतीक वापस करने के लिए कहता है। नतीजतन, #:G2867 की प्रत्येक घटना अलग प्रतीक है, और आपको अनबाउंड चरणीय चेतावनी मिलती है।

यदि आप मैक्रोक्सपेन्ड करने से पहले (setq *print-circle* t) करते हैं तो यह समान प्रतीकों को एक साथ जोड़ने के लिए #n= और #n# नोटेशन का उपयोग करेगा।

+1

लेटडा पर लेटडा का एक सेक्शन है जो इस व्यवहार पर चर्चा करता है, और क्यों जीवाश्म इस तरह से काम करते हैं, और यह वैरिएबल कैप्चर आदि से कैसे संबंधित है। यहां: http://letoverlambda.com/index.cl/guest/chap3। एचटीएमएल # sec_5 –

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