调用defpackage和in-package的变化

时间:2017-10-27 18:37:59

标签: common-lisp identifier

格雷厄姆的书“ANSI Common Lisp”(1996)p。 137说明使用 defpackage in-package 的示例就像

(defpackage "MY-APPLICATION"
  (:use "COMMON-LISP" "MY-UTILITIES")
  (:nicknames "APP")
  (:export "WIN" "LOSE" "DRAW"))

(in-package my-application)

defpackage 调用使用字符串来传递包名称和列出导出的符号。虽然这种风格可以在较旧的代码中看到,但今天的主要用途似乎是

(defpackage :my-application
  (:use :common-lisp :my-utilities)
  (:nicknames :app)
  (:export :win :lose :draw))

(in-package :my-application)

defpackage in-package 调用中使用:my-application关键字所产生的规律性是一个小但可观的差异。

我推测,第二种形式会减少内存中程序的大小,因为关键字都是在关键字包中实现的,而文字字符串代表自己,而具有相同内容的文字字符串则不会需要分享他们的记忆表示。 (如果他们这样做的话,可以通过改变其中一个字符串来获得奇怪的结果!)

这两种形式之间的实际差异是什么,为什么后者比前者更受欢迎?

除此之外,我偶尔会看到

;; Pay attention to the :export line
(defpackage :my-application
  (:use :common-lisp :my-utilities)
  (:nicknames :app)
  (:export #:win #:lose #:draw))

(in-package :my-application)

#引入了一个阅读器宏,但我不确定它对关键字有什么影响,也不确定它如何修改 defpackage 声明。

2 个答案:

答案 0 :(得分:6)

TL;博士

使用未加内容的符号,例如#:my-package

字符串指示符

普通的lisp有一个string designator的概念 (另见designators)。

这意味着操作符号 defpackage相当于 他们的名字。

使用哪个指示符?

您有4个选项:

1个实体符号

如,

(defpackage my-package)

优势

简洁

缺点

命名空间污染:符号my-package现在是 目前interned *package*

2关键字

如,

(defpackage :my-package)

优势

中等简洁(一个额外的角色)

缺点

命名空间污染:符号:my-package现在是 interned中的standard package KEYWORD

3 String

如,

(defpackage "MY-PACKAGE")

优势

没有命名空间污染。

缺点

  • Ugly upcase
  • 2个额外字符

4 Uninterned symbol

如,

(defpackage #:my-package)

优势

没有命名空间污染。

缺点

2个额外字符

"丑陋的前缀"实际上是一个理想的功能,因为这是我使用未加工符号的唯一上下文,如果添加

,emacs会很好地突出显示它们
(font-lock-add-keywords
 'lisp-mode
 '(("\\(#:\\)\\(\\(\\s_\\|\\sw\\)*\\)"
    (1 font-lock-comment-delimiter-face)
    (2 font-lock-doc-face))))

~/.emacs

答案 1 :(得分:3)

你的例子:

(defpackage "MY-APPLICATION"
  (:use "COMMON-LISP" "MY-UTILITIES")
  (:nicknames "APP")
  (:export "WIN" "LOSE" "DRAW"))

(in-package my-application)

然后通常写道:

(in-package "MY-APPLICATION")

如果您在defpackage中使用字符串,那么您也会在in-package中使用字符串。

使用字符串或非实体符号的主要优点之一是避免使用“不需要的”符号“污染”包。

  

我推测,第二种形式减少了内存中程序的大小,因为关键字都是在关键字包中实现的,而文字字符串代表它们自己,而具有相同内容的文字字符串不需要共享它们的内存表示。 (如果他们这样做的话,可以通过改变其中一个字符串来获得奇怪的结果!)

这是特定于实现的,取决于宏和底层数据结构的实现方式。例如,在包对象的LispWorks中:包名称是字符串,昵称是字符串,使用列表是包对象的列表,导出的符号存储为符号。因此,defpackage形式的数据会根据需要转换为这些数据。

还要注意包的Common Lisp运算符将返回的内容:package-name返回一个字符串,package-use-list返回一个包对象列表,do-external-symbols迭代符号。他们不使用关键字或非实体符号。