do-symbolsdo-external-symbols

do-symbols

查看一个包中的所有变量、函数和宏

  1. (do-symbols (s (find-package :PACKAGE))
  2. (print s))
  1. (let (symbols)
  2. (do-symbols (s (find-pcakge :PACKAGE))
  3. (push s symbols)
  4. symbols)
  1. (loop for s being the symbols of (find-package :PACKAGE)
  2. collect s)

do-external-symbols

查看外部可以访问的变量、函数和宏

  1. (do-external-symbols (s (find-package :PACKAGE))
  2. (print s))

其他两种方法与 do-symbols 类似。

包的别名

在定义一个包时,给包取个别名会有更好的用户体验。

  1. (defpackage hello-world
  2. (:nicknames :hello-world :hello :hw)
  3. (:export :run
  4. :is
  5. :ok)
  6. ...)

载入包后,可以使用一下任意一种方法来调用

  1. (hello-world:run)
  2. (hello:is)
  3. (hw:ok)

有点值得注意的是,不要给包定义过多的别名,否则容易让使用包的人混淆。包的别名应该具有简洁明了。

  1. (defpackage #:iterate
  2. (:nicknames #:iterate #:iter))
  3. (defpackage :cl-ppcre
  4. (:nicknames :cl-ppcre :ppcre)

导入包时可以给包另取个别名(rename-package):

  1. (asdf:load-system :cl-ppcre)
  2. (defpackage :mypackage
  3. (:use :cl))
  4. (in-package :mypackage)
  5. ;; Add nickname :RE to package :CL-PPCRE.
  6. (rename-package :cl-ppcre :cl-ppcre '(re))
  7. ;; You can use :RE instead of :CL-PPCRE now.
  8. (re:scan "a" "abc")

rename-package 的函数原型如下

  1. (rename-package package-designator name &optional (nicknames nil))

可能会有这样的疑惑,为什么不直接重命名这个包?事实上,你可以这样做,但是这种做法并不推荐。

  1. ;; DO NOT DO THIS!
  2. (rename-package :cl-ppcre :re)
  3. ;; ERROR!
  4. (cl-ppcre:scan "a" "abc")

从上面例子你可以看出,如果你直接将包给重命名了,那么你就无法使用原有的包名来进行调用。

包锁(Package locks)

一些包默认会锁定,如 common-lispsb-ext。当然,你也可以在你自定义的包中设置锁。加锁之后其他人就无法对包进行改动了。

  1. (asdf:load-system :alexandria)
  2. (rename-package :alexandria :alex)

在sbcl中运行上述代码时,会得到以下错误信息

  1. Lock on package ALEXANDRIA violated when renaming as ALEX while
  2. in package COMMON-LISP-USER.
  3. [Condition of type PACKAGE-LOCKED-ERROR]
  4. See also:
  5. SBCL Manual, Package Locks [:node]
  6. Restarts:
  7. 0: [CONTINUE] Ignore the package lock.
  8. 1: [IGNORE-ALL] Ignore all package locks in the context of this operation.
  9. 2: [UNLOCK-PACKAGE] Unlock the package.
  10. 3: [RETRY] Retry SLIME REPL evaluation request.
  11. 4: [*ABORT] Return to SLIME's top level.
  12. 5: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {10047A8433}>)
  13. ...

Common Lisp 中有一个包可以强制对加锁的包进行修改 cl-package-lock

  1. (cl-package-locks:without-package-locks
  2. (rename-package :alexandria :alex))