我有一个函数do-something
和一个函数my-function
形式:
(defun my-function ((object object))
(if (do-something)
5
6))
do-something
和my-function
在my-package
包中。
在my-package/tests
包中,我要执行以下操作:
(deftest "Test my-function"
(flet ((my-package::do-something ()
t))
(assert-is (my-package::my-function) 5))
(flet ((my-package::do-something ()
nil))
(assert-is (my-package::my-function) 6)))
目标是测试my-function
的行为是否正确,我想将其保留为一个函数(而不是宏),并且不通过args注入函数。在C语言中,我可能会弄乱链接器。
每次我想运行所有更新的代码和测试时,我都会在REPL中执行以下操作:
(ql:quickload :my-system)
(asdf:test-sytem :my-system/tests)
但是似乎它可以编译my-function
,所以即使我在测试文件中的flet
函数上执行了do-something
,行为也不会改变。
我想以编程方式测试my-function
,有没有办法做到这一点?
答案 0 :(得分:1)
由flet
(或labels
)定义的函数具有词法范围,即。例如,它们仅存在于flet
主体中。它不会影响动态环境。
没有对动态重新绑定函数的显式支持,但是您可以使用如下代码:
(defmacro with-rebound-fun ((name args &body fun-body) &body body)
(let ((saved (gensym)))
`(let ((,saved (symbol-function ',name)))
(setf (symbol-function ',name) (lambda ,args ,@fun-body))
(unwind-protect (progn ,@body)
(setf (symbol-function ',name) ,saved)))))
虽然这有点骇人听闻,但它可能会破坏一些实现可能会重新定义功能的假设。特别是,该符号可能会携带有关该功能的其他元信息,并且不会被更改。内联原始函数的地方也将不起作用。