Eğer isterseniz Dinamik kapsamı kullanarak varolan bir işlevi yeniden tanımla/gölgeleyin, bu bir süredir kullandığım bir makrodur.
(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))))))
Kullanımı: Doug Hoyte en defmacro dayanmasıdır
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>
Not! Makro, Let Over Lambda kullanılabilir. Ayrıca, yazılı olduğu gibi, anaporiktir (vücutta eğlence mevcuttur.). Tamamen hijyenik olmasını istiyorsanız, eğlence nesnelerini, g! Fun-orig'in için değiştirin.
Birim testleri yazarken çoğu zaman işlevleri yeniden tanımlarım. Belirli bir birim testi kapsamında hareket etme işlevleri yararlıdır ve bazen bunun dinamik (sözcüksel değil) kapsam ile yapılması gerekir.
Yani, sözcüksel olarak kapsamlandığı için, yalnızca flet/etiketlerin gerçek gövdesini etkileyecek ve tüm funcion çağrı hiyerarşisini değil, konuşacak? –
Tam olarak, diğer işlevler için kör bir fark yaratmayarak, yalnızca söz konusu kapsam dahilinde "var" olacak. Bildiğim kadarıyla, sembol-işlev eşleştirmelerini dinamik olarak bağlamak için herhangi bir yol yoktur. – Vatine