`intern` 函数的目的是什么?
What is the purpose of the `intern` function?
我正在关注 an article 作者定义了以下宏:
(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
函数?
删除它会破坏宏,然后 returns 错误:
The value "IS-INTEGRAL-MULTIPLE-OF-3"
is not of type
(OR SYMBOL CONS).
这是否意味着每次宏定义新符号时都必须调用 intern
? intern
在 defmacro
语句之外是否有任何用途?欢迎提供见解。
intern
找到或创建一个
具有包中提供的名称的符号。
这意味着它必须在宏创建符号时使用。
您示例中的宏是一个相当典型的用例,除了人们通常使用 #:is-integral-multiple-of-
之类的非内部符号而不是关键字 :is-integral-multiple-of-
.
在其他情况下它可能会有用。
一般来说,一个包就是一个特殊用途的table映射字符串到符号,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
获取操作员名称,帮助是 symbol-value
。
函数名称
函数名的类型必须是(OR SYMBOL CONS)
。这是 Common Lisp 标准所要求的。
因此名称必须是 symbol 或 list。通常 Lisp 中的函数名必须是符号。它们可以是列表对于 setf 函数 来说是相对特殊的。在 Common Lisp 中,它只能是一个列表,如 (setf foo)
,以 setf
作为第一个符号。在普通的 Common Lisp 中不允许使用其他列表作为函数名称。 (旁注,较旧的 Lisp Machine Lisp 有其他列表作为函数名称)。
(defun foo (bar) ; FOO is a symbol and the name of the function
(+ 42 bar))
以下是不寻常的,实际上是 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
创建符号,但该符号不会在任何包中。这使得通常很难访问该符号。
通常一个函数名应该是一个符号,它被嵌入在一些包中。仅在极少数情况下,例如某些计算代码的情况下,将未实习的符号作为函数名才有用。
我正在关注 an article 作者定义了以下宏:
(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
函数?
删除它会破坏宏,然后 returns 错误:
The value "IS-INTEGRAL-MULTIPLE-OF-3"
is not of type
(OR SYMBOL CONS).
这是否意味着每次宏定义新符号时都必须调用 intern
? intern
在 defmacro
语句之外是否有任何用途?欢迎提供见解。
intern
找到或创建一个
具有包中提供的名称的符号。
这意味着它必须在宏创建符号时使用。
您示例中的宏是一个相当典型的用例,除了人们通常使用 #:is-integral-multiple-of-
之类的非内部符号而不是关键字 :is-integral-multiple-of-
.
在其他情况下它可能会有用。
一般来说,一个包就是一个特殊用途的table映射字符串到符号,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
获取操作员名称,帮助是 symbol-value
。
函数名称
函数名的类型必须是(OR SYMBOL CONS)
。这是 Common Lisp 标准所要求的。
因此名称必须是 symbol 或 list。通常 Lisp 中的函数名必须是符号。它们可以是列表对于 setf 函数 来说是相对特殊的。在 Common Lisp 中,它只能是一个列表,如 (setf foo)
,以 setf
作为第一个符号。在普通的 Common Lisp 中不允许使用其他列表作为函数名称。 (旁注,较旧的 Lisp Machine Lisp 有其他列表作为函数名称)。
(defun foo (bar) ; FOO is a symbol and the name of the function
(+ 42 bar))
以下是不寻常的,实际上是 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
创建符号,但该符号不会在任何包中。这使得通常很难访问该符号。
通常一个函数名应该是一个符号,它被嵌入在一些包中。仅在极少数情况下,例如某些计算代码的情况下,将未实习的符号作为函数名才有用。