很难找到一个合适的标题,因为我不明白为什么我有以下问题。
当我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.")))然后,对这段代码的计算返回:
带CCL的There is no package named "FOO"
带SBCL的Package FOO does not exist
我想这样做的主要原因是,它存在不同的包,它们提供了相同的功能,并且我希望让用户可以自由地通过加载包FOO或BAR (根据条件子句中的顺序具有首选项)作出自己的选择。
发布于 2019-09-18 18:48:25
考虑以下形式的执行/评估:
(if (find-package 'foo)
(foo:foo-function))Lisp
您的错误发生在第1阶段:读取。当包不存在时,无法读取表单。
一个典型的解决方法是这样:
(if (find-package 'foo)
(funcall (find-symbol "FOO-FUNCTION" "FOO")))然后,我们在运行时查找该符号。注意,函数名和包名默认为大写。
在你的情况下,你需要打电话给
(symbol-function (find-symbol "FOO-FUNCTION" "FOO"))以获得函数对象。请注意,虽然有时它是首选的只是得到的符号。
funcall和apply可以调用作为函数对象或符号的全局函数:
(funcall 'sin 2.1d0)或
(funcall #'sin 2.1d0)因此,当需要稍后调用时,符号提供了另一个间接来源,并指向当前定义,其中函数对象也可以是函数的旧版本。
发布于 2019-09-18 20:07:22
这看起来几乎是您想要为不同实现中不同名称下可用的功能定义一个包装函数。
因为,as Rainer wrote,我们需要区分在读取时已经存在的情况,我们可以使用读取器条件。方便地,所有实现都将其名称推入*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-backend和yoursys/bar-backend,这两个系统都会将您的special-function设置为各自的实现,并依赖于所需的库。
https://stackoverflow.com/questions/57996926
复制相似问题