CL 实现之间的包系统有哪些不同?

What are the various differences in package systems between CL implementations?

在 SBCL 和 CCL 实现中使用 (make-package 'test) (in-package test) 后,我注意到 SBCL 需要 (cl:defun foo () (...))(cl:describe <symbol name here>) 而 CCL 不需要任何冒号或双冒号来使用内置-在符号中。我的理解是外部符号必须用一个冒号访问,即使它们是内置的。然而,CCL 在这方面的工作方式似乎有所不同。

这让我对外部符号的使用有些困惑。外部符号是否应该在没有任何冒号的情况下可用,或者 CCL 只是为了方便起见而自动 using/importing/inheriting?

此外,关于符号和包的实现之间是否还有这些细小但重要的差异?

ANSI CL 标准没有定义创建包时使用哪些包

在某个时间点,SBCL 偏离了惯例,但仍遵循 ANSI CL 标准。

使用包

在其他一些包中使用 包意味着在该包中使用它们的符号。

您可以通过调用函数 package-use-list.

来获取包的 use 列表

它在 ANSI Common Lisp 标准中未定义,它默认打包一个新包 uses 并且如果它 uses any .

实现中的不同常见做法

现在有两种常见的实现方式:

  • 使用 COMMON-LISP 和一些特定于实现的包。 CCL 做到了。

CCL 中的示例:

? (package-use-list (make-package "FOOBAR"))
(#<Package "CCL"> #<Package "COMMON-LISP">)

LispWorks:

CL-USER 17 > (package-use-list (make-package "FOOBAR"))
(#<The COMMON-LISP package, 0/4 internal, 978/1024 external>
 #<The HARLEQUIN-COMMON-LISP package, 0/4 internal, 365/512 external>
 #<The LISPWORKS package, 0/4 internal, 226/256 external>)
  • 使用 无包。 SBCL 就是这样做的。如果您想要一个新包 使用 包 COMMON-LISP,那么您必须明确要求。

SBCL 中的示例:

* (package-use-list (make-package "FOOBAR"))

NIL

ABCL:

CL-USER(1): (package-use-list (make-package "FOOBAR"))
NIL

编写可移植代码

因此在 SBCL 和可移植的 Common Lisp 中,你需要告诉 Lisp 哪些包应该使用。要获得 COMMON-LISPused 并且只有那个包,你需要写:

(make-package "FOO" :use '("COMMON-LISP"))

背景

第一个 Common Lisp 的最初想法是可以在 REPL 中编写 (in-package "FOO") 并且包是使用合理的默认值创建的,并且直接在该包中。默认值通常是语言包(当时称为 "LISP")和通用扩展包(例如 CLOS+MOP、线程等)。

后来更改了Common Lisp,使得IN-PACKAGE不创建包,并且定义在创建包时未定义使用哪些包,并且在创建包时不需要使用任何包。 SBCL 维护者随后想到:与其支持常见做法(标准中未提及),不如提供更中立和可预测的行为,即 在创建包时使用 no package。

其他差异

Common Lisp 中包系统的大多数其他差异都围绕着对标准的扩展。示例:

  • hierarchical/nested 包

  • 整个形式的包前缀(不仅仅是符号)

一些实现作为选项提供的更大且不兼容的更改:

  • 所有现有符号的小写和小写 reader。该标准默认将符号定义为内部大写。

未定义:

  • 其他未引用但已驻留的符号的垃圾集合