2015-07-31 7 views
6

द्वारा उत्पन्न नामों के साथ कॉल नहीं कर सकता है। मैं कुछ सामान्य डेटा के आधार पर एक से अधिक फ़ंक्शंस उत्पन्न करने के लिए ELisp मैक्रो लिखने की कोशिश कर रहा हूं। उदाहरण के लिए, जब मैं fn नाम मैं की तरह कुछ लिखने की गणना करना चाहते हैं (मैं पल के लिए स्वच्छता अनदेखी कर रहा हूँ, मैं एक प्रतीक शाब्दिक मैक्रो में तो मूल्यांकन में कोई फर्क नहीं करना चाहिए गुजर रहा हूँ):मैक्रो में परिभाषित कार्यों को कॉल-प्रतीक

(cl-defmacro def-fns (sym) 
    "SYM." 
    (let ((s1 (make-symbol (concat (symbol-name sym) "-1"))) 
     (s2 (make-symbol (concat (symbol-name sym) "-2")))) 
    `(progn (defun ,s1() (+ 1 2 3)) 
      (defun ,s2() "six")))) 

जिसे मैं आग्रह करते समय 2 एफएन उत्पन्न करने की उम्मीद करता हूं, जिसे foo-1 और foo-2 कहा जाता है।

मैं तो और FNS तो जैसे मैक्रो आह्वान करने के लिए सक्षम होना चाहिए:

(def-fns foo) 
(foo-1) 
;; => 6 
(foo-2) 
;; -> "six 

Emacs में (def-fns foo) की भी macroexpansion पता चलता है कि इस मामले होना चाहिए:

(progn 
    (defun foo-1 nil (+ 1 2 3)) 
    (defun foo-2 nil "six")) 

हालांकि, जब मैं def-fns परिभाषा का मूल्यांकन करता हूं और इसे उन कार्यों को उत्पन्न करता हूं। यह एक केस क्यों है? यह तकनीक कॉमन लिस्प और क्लोजर में काम करती है (जिसमें बहुत ही समान मैक्रो सिस्टम हैं), तो एलिसप में क्यों नहीं?

उत्तर

9

आपका कोड सीएल में भी काम नहीं करेगा।

समस्या make-symbol साथ है - यह एक नई प्रतीक बनाता है, ताकि

(eq (make-symbol "A") (make-symbol "A")) 
==> nil 

इसका मतलब यह है कि आपके मैक्रो कार्यों बनाता है, लेकिन उनमें जो तुम अब पर एक संभाल प्रतीकों को बांधता है।

जब आप (foo-1) का मूल्यांकन, Emacs लिस्प पाठक समारोह प्रशिक्षु प्रतीक foo-1, नहीं ताजा uninterned प्रतीक अपने मैक्रो बनाया के बंधन खोजने की कोशिश करता। तो बात करने के लिए यह "आम तौर पर उपलब्ध" प्रतीक बना देता है,:

(eq (intern "a") (intern "a)) 
==> t 

तो, ठीक किया कोड इस तरह दिखता है:

(defmacro def-fns (sym) 
    "SYM." 
    (let ((s1 (intern (concat (symbol-name sym) "-1"))) 
     (s2 (intern (concat (symbol-name sym) "-2")))) 
    `(progn (defun ,s1() (+ 1 2 3)) 
      (defun ,s2() "six")))) 
(def-fns foo) 
(foo-1) 
==> 6 
(foo-2) 
==> "six" 

नोट्स

इसके बजाय आप intern उपयोग करने की आवश्यकता :

  1. यदि आप सीएल का उपयोग कर रहे थे, तो अनियंत्रित प्रतीक एस #:foo-1 के रूप में मुद्रित किया गया होगा और आपकी समस्या का स्रोत आपके लिए स्पष्ट होगा।
  2. यह है दुर्लभ है कि आप वास्तव मेंmake-symbol का उपयोग करने की आवश्यकता है। आमतौर पर, आप या तो intern या gensym का उपयोग करना चाहते हैं।
+0

दरअसल। यह थोड़ी देर के बाद से मैंने सीएल/क्लोजर/एलिस्प स्टाइल मैक्रोज़ लिखा है और सीएल की तुलना में एलिसप में स्पष्ट रूप से आसान बनाने के लिए यह एक आसान गलती है :) – jjpe

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