Macros “实习生”职能的目的是什么?

Macros “实习生”职能的目的是什么?,macros,common-lisp,symbols,Macros,Common Lisp,Symbols,下面是作者定义以下宏的地方: (defmacro make-is-integral-multiple-of (n) (let ((function-name (intern (concatenate 'string (symbol-name :is-integral-multiple-of- ) (wr

下面是作者定义以下宏的地方:

(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
的用法?欢迎提供见解。

查找或创建 具有包中提供的名称的符号

这意味着在宏创建符号时必须使用它。 您的示例中的宏是一个相当典型的用例,除了人们通常使用诸如
: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))


使用
符号名称
访问操作员名称,帮助是
符号值

函数名称

函数名的类型必须为
(或符号CONS)
。这是通用Lisp标准所要求的

因此,名称需要是符号或列表。Lisp中的函数名通常必须是符号。它们可以是列表对于setf函数来说是比较特殊的。在Common Lisp中,它只能是类似于
(setf foo)
的列表,第一个符号是
setf
。普通公共Lisp中不允许使用其他列表作为函数名。(旁注,旧的Lisp机器Lisp有其他列表作为函数名)

以下是不寻常的,实际上是Common Lisp的一个功能:

(defun (setf a) (new-value thing)    ; (setf a) is the name of the function
  (setf (first thing) new-value))
使用INTERN和MAKE-SYMBOL生成函数名

因此,如果您想生成一个新的函数名,它需要是一个符号。首先将新名称生成为字符串,然后从该字符串生成符号

有几种方法可以创建符号
INTERN
将查看该符号是否已存在于包中(当前包为默认值)。如果它不存在,它将创建一个新的符号并在该包中插入该符号

也可以使用
MAKE-SYMBOL
创建符号,但该符号不会出现在任何包中。这使得通常很难访问该符号

通常,函数名应该是一个符号,它位于某个包中。只有在极少数情况下,例如在某些计算代码的情况下,将不需要的符号作为函数名才有用

(defun foo (bar)     ; FOO is a symbol and the name of the function
  (+ 42 bar))
(defun (setf a) (new-value thing)    ; (setf a) is the name of the function
  (setf (first thing) new-value))