Если вы хотите переопределить / скрыть существующую функцию, используя динамическую область видимости, это макрос, который я использовал некоторое время.
(defmacro! with-shadow ((fname fun) &body body)
"Shadow the function named fname with fun
Any call to fname within body will use fun, instead of the default function for fname.
This macro is intentionally unhygienic:
fun-orig is the anaphor, and can be used in body to access the shadowed function"
`(let ((fun-orig))
(cond ((fboundp ',fname)
(setf fun-orig (symbol-function ',fname))
(setf (symbol-function ',fname) ,fun)
(unwind-protect (progn ,@body)
(setf (symbol-function ',fname) fun-orig)))
(t
(setf (symbol-function ',fname) ,fun)
(unwind-protect (progn ,@body)
(fmakunbound ',fname))))))
Использование:
Clozure Common Lisp Version 1.9-r15759 (DarwinX8664) Port: 4005 Pid: 4728
; SWANK 2012-03-06
CL-USER>
(defun print-using-another-fname (x)
(print x))
PRINT-USING-ANOTHER-FNAME
CL-USER>
(let ((*warn-if-redefine-kernel* nil))
(with-shadow (print (lambda (x)
(funcall fun-orig (+ x 5))))
(print-using-another-fname 10)))
15
15
CL-USER>
(print 10)
10
10
CL-USER>
Обратите внимание, что это зависит от defmacro Дуга Хойта! макрос, доступный в Let Over Lambda .
Также, как написано, это анафорический (веселье доступно в теле). Если вы хотите, чтобы это было абсолютно гигиенично, просто измените fun-orig на g! Fun-orig.
Я чаще всего переопределяю функции при написании модульных тестов. Полезны фиктивные функции в рамках определенного модульного теста, и иногда это необходимо делать с динамической (не лексической) областью действия.