2011-05-04 102 views
11

我意識到,我的代碼的某個部分由看起來相似的方法組組成(例如,我有多個三重奏:一個輔助函數,可以通過另外兩個爲程序員設計的函數調用)。我試圖編寫一個宏來爲我定義這三個函數,以便我需要做的就是調用宏。但是我的嘗試導致defuns和函數調用引用了字符串,而不是生成的名稱作爲新符號。我究竟做錯了什麼?common lisp:宏如何用程序生成的名稱定義其他方法/宏?

例(不正確的代碼)

(defmacro def-trio (base-name) 
    (let 
    ((helper-name (format nil "helper-~a" base-name)) 
    (method-1 (format nil "~a-1" base-name)) 
    (method-2 (format nil "~a-2" base-name))) 
    `(progn 
      (defun ,helper-name() 'helper-called) 
      (defun ,method-1() (,helper-name) '1-called) 
      (defun ,method-2() (,helper-name) '2-called)))) 

現在會發生以下情況:

(def-trio my-trio) 

==>

(PROGN (DEFUN "helper-MY-TRIO"() 'HELPER-CALLED) 
     (DEFUN "MY-TRIO-1"() ("helper-MY-TRIO") '1-CALLED) 
     (DEFUN "MY-TRIO-2"() ("helper-MY-TRIO") '2-CALLED)) 

而且,以後我學會如何得到這個工作,是還有什麼額外的困難,如果我有這個宏定義其他宏而不是其他函數?我讀How do I write a macro-defining macro in common lisp但我認爲我的問題有點不同,因爲我詢問了有關程序生成的符號/名稱。我打開要糾正,但:)謝謝!

+0

請將'宏定義其他宏'作爲單獨的帖子提交,因爲它沒有密切關聯。 – 2011-05-04 21:29:30

回答

5

使用INTERN將生成的函數名稱字符串轉換爲符號。

7

試試這個:

 
(defmacro def-trio (base-name)           ; changes: 
    (let*                ; 3. 
    ((package (symbol-package base-name))        ; 2. 
    (helper-name (intern (format nil "HELPER-~a" base-name)package)) ; 1. 4. 
    (method-1 (intern (format nil "~a-1" base-name) package))   ; 1. 
    (method-2 (intern (format nil "~a-2" base-name) package)))  ; 1. 
    `(progn 
      (defun ,helper-name() 'helper-called) 
      (defun ,method-1() (,helper-name) '1-called) 
      (defun ,method-2() (,helper-name) '2-called)))) 

下更改了原來的定義所做的 - 第一個變化是關鍵的一條:

  1. 每一所計算的符號名實習進入同一個包基本名稱使用(intern ... package)
  2. 引入了與提供的base-name符號的包綁定的變量package
  3. let更改爲let*以允許在後續變量中引用新引入的變量package
  4. 將幫助器方法的前綴更改爲大寫以匹配常規Lisp符號的約定。
+0

感謝您的詳細幫助!在發佈之前,我得到了一些工作,但我的代碼並未明確說明哪些程序包用於實習調用。 – nil 2011-05-11 14:19:26