2016-10-02 64 views
2

我下面an article這裏筆者定義了以下宏:`intern`功能的目的是什麼?

(defmacro make-is-integral-multiple-of (n) 
    (let ((function-name (intern (concatenate 
           'string 
           (symbol-name :is-integral-multiple-of-) 
           (write-to-string n))))) 
    `(defun ,function-name (x) 
     (equal 0 (mod x, n))))) 

宏很容易閱讀和理解,但我想知道:什麼時候,爲什麼我們需要明確的intern功能?

刪除它打破了宏,然後返回錯誤:

The value "IS-INTEGRAL-MULTIPLE-OF-3" 
is not of type 
    (OR SYMBOL CONS). 

這是否意味着intern必須調用每一個宏應該定義一個新的符號時間?在defmacro陳述之外是否有任何用途intern?深刻的見解是值得的。

回答

3

函數名

一個函數的名稱必須是(OR SYMBOL CONS)類型。這是Common Lisp標準所要求的。

因此,名稱需要是符號或列表。通常Lisp中的函數名稱必須是符號。它們可以是列表對於setf函數是比較特殊的。在Common Lisp中,它只能是像(setf foo)這樣的列表,其中setf作爲第一個符號。其他列表作爲函數名稱在普通Common Lisp中是不允許的。

與實習生生成函數名稱,使符號

所以,如果你想生成一個新的函數名,它必須是一個符號。首先以字符串形式生成新名稱,然後從該字符串中生成一個符號。

有幾種創建符號的方法。 INTERN將查看包中是否已經存在該符號(當前包是默認包)。如果它不存在,它會在該包中創建一個新的符號。

也可以使用MAKE-SYMBOL來創建符號,但該符號不在任何包中。這使得通常很難訪問該符號。

通常一個函數名應該是一個符號,它被封裝在一些包中。只有在極少數情況下,例如計算代碼的某些情況下,將未插入符號作爲函數名稱會很有用。

3

intern找到或創建一個包含提供名稱的 符號。

這意味着它在宏將創建一個符號時使用。 在你的例子中的宏是一個相當典型的用例,除了人們通常使用未插入的符號,如#:is-integral-multiple-of-而不是關鍵字:is-integral-multiple-of-

還有其他一些可能有用的情況。 一般而言,包是一個將字符串映射到符號的特殊用途表,intern對應於(setf gethash)

例如,你可以使用以下方法之一,讓您的數據:

(defvar *operators* (make-hash-table :test 'equal)) 
(defstruct operator name help function) 
(defun make-op (name help function) 
    (setf (gethash name *operators*) 
     (make-operator :name name 
         :help help 
         :function function))) 
(make-op "build-house" 
     "construct a house out of the supplied materials" 
     (lambda (bricks mortar) ...)) 
(funcall (operator-function (gethash "build-house" *operators*)) 
     (list "brick1" "brick2" ...) 
     (make-mortar)) 

(defpackage #:operators) 
(defun make-op (name help function) 
    (let ((op (intern name #:operators))) 
    (setf (symbol-value op) help 
      (fdefinition op) function))) 
(make-op "build-house" 
     "construct a house out of the supplied materials" 
     (lambda (bricks mortar) ...)) 
(funcall #'operators::build-house 
     (list "brick1" "brick2" ...) 
     (make-mortar)) 

運營商名稱使用symbol-name asscessed,幫助symbol-value