flet
的问题是其中绑定(bind)的函数必须内联定义。换句话说,没有办法做到这一点:
(new-flet ((a (lambda (f x)
(funcall f (* x 2))))
(b (function-generator)))
(a #'b 10))
我考虑过自己定义这样一个宏,但问题是 flet
似乎是设置局部函数值的唯一方式。 symbol-function
始终只获取全局定义,function
不能与 setf
一起使用。任何人都知道如何相当干净地完成这项工作(如果有的话)?
最佳答案
你可以轻松地搭建一个蹦床
(defun function-generator (x)
(lambda (y) (* x y)))
(let ((fg (function-generator 42)))
(flet ((a (f x) (funcall f (* x 2)))
(b (x) (funcall fg x)))
(a #'b 10)))
new-flet
的宏实现是
(defmacro new-flet (bindings &body body)
(let ((let-bindings (list))
(flet-bindings (list))
(args (gensym)))
(dolist (binding bindings)
(let ((name (gensym)))
(push `(,name ,(second binding))
let-bindings)
(push `(,(first binding) (&rest ,args)
(apply ,name ,args))
flet-bindings)))
`(let ,(nreverse let-bindings)
(flet ,(nreverse flet-bindings)
,@body))))
在您的示例中扩展为
(macroexpand-1 '(new-flet ((a (lambda (f x) (funcall f (* x 2))))
(b (function-generator)))
(a #'b 10)))
==> (LET ((#:G605 (LAMBDA (F X)
(FUNCALL F (* X 2))))
(#:G606 (FUNCTION-GENERATOR)))
(FLET ((A (&REST #:G604)
(APPLY #:G605 #:G604))
(B (&REST #:G604)
(APPLY #:G606 #:G604)))
(A #'B 10)))
关于lisp - 如何使用函数(或闭包)对象设置局部函数定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18362073/