lisp - 如何使用函数(或闭包)对象设置局部函数定义?

标签 lisp common-lisp

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/

相关文章:

windows - 为什么 lisp 数到十亿这么慢?

clojure - lisp 宏在典型开发中真的有用吗?

common-lisp - Common Lisp 中格式指令的安全解析

post - Hunchentoot 处理复选框发布请求

algorithm - Common Lisp 中的线性递归列表差函数

lisp - 在 Lisp 函数中定义一个语法错误

list - 为什么用 cons() 和 list() 创建的列表显示不同?

lisp - clisp,CLOS : retyping an object, 之后

macros - 是否有用于从列表中弹出第 n 个元素的通用 lisp 宏?

common-lisp - 从使用的外部包访问 CLOS 对象槽