LISP cond answer 无包

LISP cond answer no package

很难找到合适的标题,因为我不明白为什么会出现以下问题。

当我require我的包时,我想根据一些包分配特定的功能。这个想法是设置一个变量如下:

(cond ((find-package 'foo) (setf *special-function* #'foo:foo-function))
      ((find-package 'bar) (setf *special-function* #'bar:bar-function))
      (t (warn "The package FOO or BAR is required to enable the special function.")))

然后,对这段代码的评价returns:

There is no package named "FOO" 与 CCL

Package FOO does not exist 与 SBCL

我想这样做的主要原因是它存在提供相同功能的不同包,我想让用户通过加载包 FOO 或 BAR(有偏好根据条件子句中的顺序)。

想想下面形式的execution/evaluation:

(if (find-package 'foo)
    (foo:foo-function))

Lisp

  1. 阅读代码
  2. 然后计算代码。

您的错误发生在第 1 阶段:阅读。当包不存在时,无法读取表单。

一个典型的解决方法是这样的:

(if (find-package 'foo)
    (funcall (find-symbol "FOO-FUNCTION" "FOO")))

然后我们在运行时查找符号。请注意,函数和包名称默认为大写。

在您的情况下,您需要致电

(symbol-function (find-symbol "FOO-FUNCTION" "FOO"))

获取函数对象。请注意,有时最好只获取符号。

funcallapply 可以将全局函数作为函数对象或符号调用:

(funcall 'sin 2.1d0)

(funcall #'sin 2.1d0)

因此当稍后需要调用该事物时,符号提供了另一个间接来源并将指向当前定义,其中函数对象也可以是该函数的旧版本。

这看起来就像您想为在不同实现中以不同名称提供的功能定义包装函数。

由于,我们需要在阅读时区分大小写,为此我们可以使用reader条件。方便的是,所有实现都将它们的名字推送到 *features*,这样我们就可以这样做:

(defun special-function (&rest args)
  #+sbcl (apply #'foo:foo-function args)
  #+ccl (apply #'bar:bar-function args)
  #-(or sbcl ccl) (error "not implemented))

相反,如果您想允许不同的库来填充您的功能,您可以依靠用户在加载系统之前加载其中一个库,如果这些库将它们自己的符号推送到 *features*,或者您可以定义添加可选依赖项的小包装系统:

示例:您的 (asdf) 系统名为 yoursys,那么您可以定义另一个系统 yoursys/foo-backendyoursys/bar-backend,这两个系统都会将您的 special-function 设置为它们各自的实现,并取决于所需的库。