关键字命名空间污染

dar*_*ine 2 symbols common-lisp

我明白之间的区别

(defpackage :foo
  (:export :bar))
Run Code Online (Sandbox Code Playgroud)

(defpackage :foo
  (:export #:bar))
Run Code Online (Sandbox Code Playgroud)

是后者不会实习bar到包中KEYWORD。我的问题是,这样做有意义吗?毕竟,这个包的目的似乎KEYWORD是用于实习关键字。

Rai*_*wig 5

包用于维护符号的名称空间。包有名称,符号也有名称。通常,人们将这些名称作为字符串获取,因此 defpackage 形式可以使用字符串作为名称:

(defpackage "FOO"
  (:export "BAR"))
Run Code Online (Sandbox Code Playgroud)

有些人不喜欢上面的包描述,因为它暴露了标识符的大小写。通常这不是问题,但 Common Lisp 有非标准版本,其中符号默认情况下可能是小写的。

由于可以使用符号作为名称(并且只有名称才有意义),DEFPACKAGE我们可以这样写:

(defpackage :foo
  (:export :bar))
Run Code Online (Sandbox Code Playgroud)

或者

(defpackage #:foo
  (:export #:bar))
Run Code Online (Sandbox Code Playgroud)

甚至

(defpackage cl-user::foo
  (:export cl-user::bar))


CL-USER 22 > (find-symbol "BAR" "FOO")
FOO:BAR
:EXTERNAL
Run Code Online (Sandbox Code Playgroud)

通常的期望是,垃圾收集器(GC)可能不会删除包中未引用的符号- Common Lisp 标准没有提及此主题,也没有任何必需的行为。因此,向包中添加新符号通常会使其不断增长。在某些应用程序中这可能是内存泄漏。

另一个通常的期望是未引用未驻留的符号将由 GC 释放。

如果您不介意关键字 package中有很多无论这意味着什么)符号,那么这不是问题。

大包的典型问题可能是:

  • 保留的符号不能被 GC 处理
  • 使用大型包可能会产生一些速度成本

对于典型的DEFPACKAGE形式,我预计不会出现任何明显的问题,因此无论出于何种风格原因,人们可能更喜欢一种变体。

  • 我在“defpackage”中使用未驻留符号(例如“#:symbol”)的主要原因是为了使用当前可读的区分大小写模式或特定于实现的大小写模式来读取其名称,这是您不能做的用一根绳子。与关键字或限定或非限定符号相比,我还更喜欢未驻留符号,因为不在读取时驻留符号,不在编译文件中存储包名称,这也避免了在加载时驻留,进而避免名称冲突。 (2认同)