Common Lisp 将包名称附加到宏中引用的键
Common Lisp appending package name to quoted keys in macros
我注意到 Common Lisp 中的以下行为(至少使用 SBCL),我能够将其减少为以下内容:
假设我有以下宏:
(defpackage "MY-TEST"
(:use "COMMON-LISP")
(:export :appended
:not-appended))
(in-package :MY-TEST)
(defmacro not-appended ()
`(list ':type 'array))
(defmacro appended ()
`(list ':type 'something-else))
输出如下:
* (my-test:not-appended)
(:TYPE ARRAY)
* (my-test:appended)
(:TYPE MY-TEST::SOMETHING-ELSE)
请注意,在第二个宏中,命名空间位于 "SOMETHING-ELSE".
之前
问题:
- 为什么他们不一样?老实说,我期待 "not-appended" 宏的行为。那是因为 Common Lisp 以某种方式知道 "array" 吗?
- 如果是,那么我在哪里可以找到其他已知关键字?
请注意,这与宏完全无关,是包、符号和符号打印方式的影响:
软件包“MY-TEST”:
CL-USER 2 > (defpackage "MY-TEST"
(:use "COMMON-LISP")
(:export :appended
:not-appended))
#<The MY-TEST package, 0/16 internal, 2/16 external>
通过调用 in-package
:
使包成为当前包
CL-USER 3 > (in-package :MY-TEST)
#<The MY-TEST package, 0/16 internal, 2/16 external>
让我们计算一个符号列表 array
和 foo
。查看 REPL 如何将其打印为 (ARRAY FOO)
,因为这两个符号都可以在包 MY-TEST
.
中访问
MY-TEST 4 > (list 'array 'foo)
(ARRAY FOO)
使CL-USER
成为当前包:
MY-TEST 5 > (in-package :cl-user)
#<The COMMON-LISP-USER package, 151/256 internal, 0/4 external>
现在让我们获取倒数第二个值,看看 REPL 是如何打印它的:
CL-USER 6 > **
(ARRAY MY-TEST::FOO)
ARRAY
打印时没有包前缀,因为它与包 COMMON-LISP
中的符号相同(在包 MY-TEST
中使用)。 FOO
与包前缀 MY-TEST
一起打印,因为它是该包中的内部符号 - 它被保留在那里,因为当前包是 MY-TEST
。有两个冒号,因为符号 FOO
没有从包 MY-TEST
导出,也没有导入包 CL-USER
.
包 "CL" 和 "CL-USER" 包含编程语言 Common Lisp 中的所有符号 - 因此将 "CL" 导入您自己的包中可以使所有这些符号在该包中可用,也是。
CL-USER 7 > (let ((l '()))
(do-symbols (sym (find-package "CL") l)
(pushnew sym l)))
(MAKE-ARRAY INVOKE-DEBUGGER STRING-TRIM WILD-PATHNAME-P UNREAD-CHAR RESTART-BIND ...
我注意到 Common Lisp 中的以下行为(至少使用 SBCL),我能够将其减少为以下内容:
假设我有以下宏:
(defpackage "MY-TEST"
(:use "COMMON-LISP")
(:export :appended
:not-appended))
(in-package :MY-TEST)
(defmacro not-appended ()
`(list ':type 'array))
(defmacro appended ()
`(list ':type 'something-else))
输出如下:
* (my-test:not-appended)
(:TYPE ARRAY)
* (my-test:appended)
(:TYPE MY-TEST::SOMETHING-ELSE)
请注意,在第二个宏中,命名空间位于 "SOMETHING-ELSE".
之前问题:
- 为什么他们不一样?老实说,我期待 "not-appended" 宏的行为。那是因为 Common Lisp 以某种方式知道 "array" 吗?
- 如果是,那么我在哪里可以找到其他已知关键字?
请注意,这与宏完全无关,是包、符号和符号打印方式的影响:
软件包“MY-TEST”:
CL-USER 2 > (defpackage "MY-TEST"
(:use "COMMON-LISP")
(:export :appended
:not-appended))
#<The MY-TEST package, 0/16 internal, 2/16 external>
通过调用 in-package
:
CL-USER 3 > (in-package :MY-TEST)
#<The MY-TEST package, 0/16 internal, 2/16 external>
让我们计算一个符号列表 array
和 foo
。查看 REPL 如何将其打印为 (ARRAY FOO)
,因为这两个符号都可以在包 MY-TEST
.
MY-TEST 4 > (list 'array 'foo)
(ARRAY FOO)
使CL-USER
成为当前包:
MY-TEST 5 > (in-package :cl-user)
#<The COMMON-LISP-USER package, 151/256 internal, 0/4 external>
现在让我们获取倒数第二个值,看看 REPL 是如何打印它的:
CL-USER 6 > **
(ARRAY MY-TEST::FOO)
ARRAY
打印时没有包前缀,因为它与包 COMMON-LISP
中的符号相同(在包 MY-TEST
中使用)。 FOO
与包前缀 MY-TEST
一起打印,因为它是该包中的内部符号 - 它被保留在那里,因为当前包是 MY-TEST
。有两个冒号,因为符号 FOO
没有从包 MY-TEST
导出,也没有导入包 CL-USER
.
包 "CL" 和 "CL-USER" 包含编程语言 Common Lisp 中的所有符号 - 因此将 "CL" 导入您自己的包中可以使所有这些符号在该包中可用,也是。
CL-USER 7 > (let ((l '()))
(do-symbols (sym (find-package "CL") l)
(pushnew sym l)))
(MAKE-ARRAY INVOKE-DEBUGGER STRING-TRIM WILD-PATHNAME-P UNREAD-CHAR RESTART-BIND ...