defpackage 和 in-package 调用的变化
Variations in invocation of defpackage and in-package
在格雷厄姆的书“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
关键字的规律性是细微但明显的差异。
我推测,第二种形式减少了程序在内存中的大小,因为关键字都驻留在 keyword 包中,而文字字符串代表它们自己和文字字符串具有相同内容的对象不需要共享它们的内存表示。 (如果他们这样做了,改变其中一个字符串可能会产生奇怪的结果!)
这两种形式之间的实际区别是什么,为什么后者优于前者?
除此之外,我偶尔会看到
;; Pay attention to the :export line
(defpackage :my-application
(:use :common-lisp :my-utilities)
(:nicknames :app)
(:export #:win #:lose #:draw))
(in-package :my-application)
#
引入了一个 reader 宏,但我不确定它对关键字有什么影响,也不确定它如何修改 defpackage 声明.
tl;博士
使用未固定的符号,例如 #:my-package
。
字符串指示符
Common lisp 有一个 string 的概念
代号
(另请参阅 designators)。
这意味着操作符号在
defpackage
相当于
他们的名字。
使用哪个代号?
您有 4 个选项:
1 个内部符号
例如,
(defpackage my-package)
优势
简洁
缺点
命名空间污染:符号 my-package
现在是
interned 在当前
*package*
.
2 个关键字
例如,
(defpackage :my-package)
优势
中等简洁(多一个字符)
缺点
命名空间污染:符号 :my-package
现在是
interned 在 标准包中
关键字.
3 个字符串
例如,
(defpackage "MY-PACKAGE")
优势
没有命名空间污染。
缺点
- 难看的大写
- 2 个额外字符
4 未嵌入的符号
例如,
(defpackage #:my-package)
优势
没有命名空间污染。
缺点
2 个额外字符
"ugly prefix" 实际上是一个令人满意的功能,因为这是我唯一使用非内部符号的上下文,如果添加
,emacs 会很好地突出显示它们
(font-lock-add-keywords
'lisp-mode
'(("\(#:\)\(\(\s_\|\sw\)*\)"
(1 font-lock-comment-delimiter-face)
(2 font-lock-doc-face))))
给你的 ~/.emacs
.
你的例子:
(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
中使用字符串。
使用字符串或非内部符号的主要优点之一是避免 'polluting' 包含 'unwanted' 符号的包。
I speculate, the second forms reduces the size of the program in memory because the keywords are all interned in the keyword package while literal character strings stand for themselves and literal character strings with identical contents do not need to share their memory representations. (And if they did, strange results could follow from mutating one of these character strings!)
这是特定于实现的,取决于宏和底层数据结构的实现方式。例如在LispWorks中对于包对象:包名是一个字符串,昵称是字符串,使用列表是包对象的列表,导出的符号作为符号存储。因此,defpackage
形式的数据会根据需要转换为这些形式。
还要注意包的 Common Lisp 运算符 return:package-name
return 是一个字符串,package-use-list
return 是一个包对象列表, do-external-symbols
遍历符号。他们不使用关键字或 un-interned 符号。
在格雷厄姆的书“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
关键字的规律性是细微但明显的差异。
我推测,第二种形式减少了程序在内存中的大小,因为关键字都驻留在 keyword 包中,而文字字符串代表它们自己和文字字符串具有相同内容的对象不需要共享它们的内存表示。 (如果他们这样做了,改变其中一个字符串可能会产生奇怪的结果!)
这两种形式之间的实际区别是什么,为什么后者优于前者?
除此之外,我偶尔会看到
;; Pay attention to the :export line
(defpackage :my-application
(:use :common-lisp :my-utilities)
(:nicknames :app)
(:export #:win #:lose #:draw))
(in-package :my-application)
#
引入了一个 reader 宏,但我不确定它对关键字有什么影响,也不确定它如何修改 defpackage 声明.
tl;博士
使用未固定的符号,例如 #:my-package
。
字符串指示符
Common lisp 有一个 string 的概念 代号 (另请参阅 designators)。
这意味着操作符号在
defpackage
相当于
他们的名字。
使用哪个代号?
您有 4 个选项:
1 个内部符号
例如,
(defpackage my-package)
优势
简洁
缺点
命名空间污染:符号 my-package
现在是
interned 在当前
*package*
.
2 个关键字
例如,
(defpackage :my-package)
优势
中等简洁(多一个字符)
缺点
命名空间污染:符号 :my-package
现在是
interned 在 标准包中
关键字.
3 个字符串
例如,
(defpackage "MY-PACKAGE")
优势
没有命名空间污染。
缺点
- 难看的大写
- 2 个额外字符
4 未嵌入的符号
例如,
(defpackage #:my-package)
优势
没有命名空间污染。
缺点
2 个额外字符
"ugly prefix" 实际上是一个令人满意的功能,因为这是我唯一使用非内部符号的上下文,如果添加
,emacs 会很好地突出显示它们(font-lock-add-keywords
'lisp-mode
'(("\(#:\)\(\(\s_\|\sw\)*\)"
(1 font-lock-comment-delimiter-face)
(2 font-lock-doc-face))))
给你的 ~/.emacs
.
你的例子:
(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
中使用字符串。
使用字符串或非内部符号的主要优点之一是避免 'polluting' 包含 'unwanted' 符号的包。
I speculate, the second forms reduces the size of the program in memory because the keywords are all interned in the keyword package while literal character strings stand for themselves and literal character strings with identical contents do not need to share their memory representations. (And if they did, strange results could follow from mutating one of these character strings!)
这是特定于实现的,取决于宏和底层数据结构的实现方式。例如在LispWorks中对于包对象:包名是一个字符串,昵称是字符串,使用列表是包对象的列表,导出的符号作为符号存储。因此,defpackage
形式的数据会根据需要转换为这些形式。
还要注意包的 Common Lisp 运算符 return:package-name
return 是一个字符串,package-use-list
return 是一个包对象列表, do-external-symbols
遍历符号。他们不使用关键字或 un-interned 符号。