2015-11-15 23 views
6

जब मैं निम्नलिखित कोड संकलित करता हूं, तो एसबीसीएल शिकायत करता है कि जी! -निट-वैल्यू और जी! -निट अपरिभाषित हैं। मुझे यकीन नहीं है कि इसे कैसे डिबग करें। जहां तक ​​मैं कह सकता हूं, फ़्लैटन असफल हो रहा है।मैक्रोज़ जो मैक्रोज़ लिखते हैं - संकलन त्रुटि

जब flatten defunits के निर्विवाद हिस्से तक पहुंचता है, ऐसा लगता है कि पूरे हिस्से को परमाणु के रूप में माना जा रहा है। क्या यह सही लगता है?

निम्नलिखित पुस्तक Let over Lambda से कोड का उपयोग करता है:

पॉल ग्राहम उपयोगिताएँ

(defun symb (&rest args) 
    (values (intern (apply #'mkstr args)))) 

(defun mkstr (&rest args) 
    (with-output-to-string (s) 
    (dolist (a args) (princ a s)))) 

(defun group (source n) 
    (if (zerop n) (error "zero length")) 
    (labels ((rec (source acc) 
      (let ((rest (nthcdr n source))) 
       (if (consp rest) 
        (rec rest (cons (subseq source 0 n) acc)) 
        (nreverse (cons source acc)))))) 
    (if source (rec source nil) nil))) 

(defun flatten (x) 
    (labels ((rec (x acc) 
      (cond ((null x) acc) 
        ((atom x) (cons x acc)) 
        (t (rec (car x) (rec (cdr x) acc)))))) 
    (rec x nil))) 

चलो ओवर लैम्ब्डा उपयोगिताएँ - अध्याय 3

(defmacro defmacro/g! (name args &rest body) 
    (let ((g!-symbols (remove-duplicates 
       (remove-if-not #'g!-symbol-p 
           (flatten body))))) 
    `(defmacro ,name ,args 
     (let ,(mapcar 
       (lambda (g!-symbol) 
       `(,g!-symbol (gensym ,(subseq 
             (symbol-name g!-symbol) 
             2)))) 
       g!-symbols) 
     ,@body)))) 

(defun g!-symbol-p (symbol-to-test) 
    (and (symbolp symbol-to-test) 
     (> (length (symbol-name symbol-to-test)) 2) 
     (string= (symbol-name symbol-to-test) 
       "G!" 
       :start1 0 
       :end1 2))) 

(defmacro defmacro! (name args &rest body) 
    (let* ((o!-symbols (remove-if-not #'o!-symbol-p args)) 
     (g!-symbols (mapcar #'o!-symbol-to-g!-symbol o!-symbols))) 
    `(defmacro/g! ,name ,args 
     `(let ,(mapcar #'list (list ,@g!-symbols) (list ,@o!-symbols)) 
      ,(progn ,@body))))) 

(defun o!-symbol-p (symbol-to-test) 
    (and (symbolp symbol-to-test) 
     (> (length (symbol-name symbol-to-test)) 2) 
     (string= (symbol-name symbol-to-test) 
       "O!" 
       :start1 0 
       :end1 2))) 

(defun o!-symbol-to-g!-symbol (o!-symbol) 
    (symb "G!" (subseq (symbol-name o!-symbol) 2))) 

चलो ओवर लैम्ब्डा - अध्याय 5

(defun defunits-chaining (u units prev) 
    (if (member u prev) 
     (error "~{ ~a~^ depends on~}" 
      (cons u prev))) 
    (let ((spec (find u units :key #'car))) 
    (if (null spec) 
     (error "Unknown unit ~a" u) 
     (let ((chain (second spec))) 
      (if (listp chain) 
       (* (car chain) 
       (defunits-chaining 
        (second chain) 
        units 
        (cons u prev))) 
       chain))))) 

(defmacro! defunits (quantity base-unit &rest units) 
    `(defmacro ,(symb 'unit-of- quantity) 
     (,g!-unit-value ,g!-unit) 
    `(* ,,g!-unit-value 
     ,(case ,g!-unit 
       ((,base-unit) 1) 
       ,@(mapcar (lambda (x) 
          `((,(car x)) 
           ,(defunits-chaining 
           (car x) 
           (cons 
           `(,base-unit 1) 
           (group units 2)) 
           nil))) 
          (group units 2)))))) 
+0

किसी कारण से फ़ंक्शन g! -symbol-p क्लोजर कॉमन लिस्प संस्करण 1.11 (DarwinX8664) में संकलित नहीं है! –

+0

क्या कुछ ऐसा है जो एसबीसीएल कर रहा था? – SpyroSoft

उत्तर

6

इस तरह के मुश्किल है:

समस्या: आप मानते हैं कि backquote/अल्पविराम भाव सादा सूची नहीं है।

आप अपने आप को इस सवाल पूछना चाहिए:

एक backquote/अल्पविराम अभिव्यक्ति का प्रतिनिधित्व क्या है?

क्या यह एक सूची है?

दरअसल पूर्ण प्रतिनिधित्व अनिर्दिष्ट है। यहां देखें: CLHS: Section 2.4.6.1 Notes about Backquote

हम एसबीसीएल का उपयोग कर रहे हैं। देखें:

* (setf *print-pretty* nil) 

NIL 


* '`(a ,b) 

(SB-INT:QUASIQUOTE (A #S(SB-IMPL::COMMA :EXPR B :KIND 0))) 

तो एक अल्पविराम अभिव्यक्ति प्रकार SB-IMPL::COMMA की एक संरचना का प्रतिनिधित्व करती है। एसबीसीएल डेवलपर्स ने सोचा कि यह प्रतिनिधित्व तब मदद करता है जब सुंदर बैकक्वॉट सूचियों को सुंदर प्रिंटर द्वारा मुद्रित करने की आवश्यकता होती है।

परमाणुओं के रूप में अपने flatten व्यवहार करता है संरचनाओं के बाद से, इसके अंदर दिखेगा नहीं ...

लेकिन इस SBCL के विशिष्ट प्रतिनिधित्व है। क्लोजर सीएल कुछ और करता है और LispWorks फिर से कुछ और करता है।

Clozure CL:

? '`(a ,b) 
(LIST* 'A (LIST B)) 

LispWorks:

CL-USER 87 > '`(a ,b) 
(SYSTEM::BQ-LIST (QUOTE A) B) 

डिबगिंग

जब से तुम को पता चला है कि किसी तरह flatten शामिल किया गया था, अगले डिबगिंग कदम हैं:

सबसे पहले: फंक्शन flatten का पता लगाएं और देखें कि किस डेटा को इसे कॉल किया जाता है और यह क्या लौटाता है।

चूंकि हम निश्चित नहीं हैं कि डेटा वास्तव में क्या है, कोई INSPECT कर सकता है।

एक डिबगिंग उदाहरण SBCL का उपयोग कर:

* (defun flatten (x)                       
    (inspect x)                        
    (labels ((rec (x acc)                      
       (cond ((null x) acc)                   
        ((atom x) (cons x acc))                 
        (t (rec (car x) (rec (cdr x) acc))))))             
     (rec x nil))) 
STYLE-WARNING: redefining COMMON-LISP-USER::FLATTEN in DEFUN 

FLATTEN 

से ऊपर तर्क डेटा पर INSPECT कहता है। आम लिस्प में, इंस्पेक्टर आमतौर पर ऐसा कुछ होता है जहां कोई डेटा संरचनाओं का निरीक्षण कर सकता है।

एक उदाहरण हम एक backquote अभिव्यक्ति के साथ flatten बुला रहे हैं के रूप में:

* (flatten '`(a ,b)) 

The object is a proper list of length 2. 
0. 0: SB-INT:QUASIQUOTE 
1. 1: (A ,B) 

हम इंटरैक्टिव निरीक्षक में हैं। आदेशों अब उपलब्ध:

> help 

help for INSPECT: 
    Q, E  - Quit the inspector. 
    <integer> - Inspect the numbered slot. 
    R   - Redisplay current inspected object. 
    U   - Move upward/backward to previous inspected object. 
    ?, H, Help - Show this help. 
    <other>  - Evaluate the input as an expression. 
Within the inspector, the special variable SB-EXT:*INSPECTED* is bound 
to the current inspected object, so that it can be referred to in 
evaluated expressions. 

तो आदेश 1 डेटा संरचना, यहाँ एक सूची में चलता है। आगे में

> 1 

The object is a proper list of length 2. 
0. 0: A 
1. 1: ,B 

वॉक:

> 1 

The object is a STRUCTURE-OBJECT of type SB-IMPL::COMMA. 
0. EXPR: B 
1. KIND: 0 

यहाँ इंस्पेक्टर हमें बताता है कि वस्तु एक खास प्रकार की एक संरचना है। यही वह है जिसे हम जानना चाहते थे।

अब हम इंस्पेक्टर छोड़ आदेश q और flatten समारोह जारी है और एक मान देता है का उपयोग करते हुए:

> q 

(SB-INT:QUASIQUOTE A ,B) 
+0

धन्यवाद। वाह, यह एक संरचना है। मुझे नहीं लगता कि किसी ने पोर्टेबल क्वासिकोट लाइब्रेरी बनाई है, है ना? – SpyroSoft

+1

यह वही स्पष्टीकरण है जिसे मैं समझना चाहता था कि defmacro/g क्यों! एलओएल के चैप 3 में परिभाषित मैक्रो (http://letoverlambda.com/index.cl/guest/chap3.html) काम नहीं कर रहा है! धन्यवाद –

0

किसी और को जो defmacro पाने के लिए कोशिश कर रहा है के लिए! SBCL पर काम करने, इस समस्या का एक अस्थायी समाधान समतल प्रक्रिया के दौरान गंदें शब्द बोलना संरचना के भीतर टटोलना रिकर्सिवली इसकी सामग्री समतल है:

(defun flatten (x) 
    (labels ((flatten-recursively (x flattening-list) 
      (cond ((null x) flattening-list) 
        ((eq (type-of x) 'SB-IMPL::COMMA) (flatten-recursively (sb-impl::comma-expr x) flattening-list)) 
        ((atom x) (cons x flattening-list)) 
        (t (flatten-recursively (car x) (flatten-recursively (cdr x) flattening-list)))))) 
    (flatten-recursively x nil))) 

लेकिन यह बुरी तरह मंच निर्भर है। अगर मुझे एक बेहतर तरीका मिल जाए, तो मैं इसे पोस्ट करूंगा।

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