我在foo
中定义了一系列我想要在bar
中使用的函数。我在foo
中定义了这些函数,因为我希望foo
是自包含的 - 否则我知道我可以在外部(全局)定义这些函数,以便foo
和{bar
可以访问{1}}和其他函数,或在foo
构造中定义bar
和labels
,其中仅为foo
和bar
定义了这些函数。无论如何,我希望foo
可以在没有外部函数或labels
结构的情况下进行分发。因此挑战。
这是我到目前为止(在这种情况下我使用的是Emacs Lisp),但是当我调用foo
时,我现在最终在全局bar
中定义本地函数。有关如何在bar
“动态”定义局部变量/函数的任何建议吗?
(defun foo (x)
(flet ((addone (x) (1+ x))
(addtwo (x) (+ 2 x)))
(addtwo x)))
(defun bar (x)
(let* ((fnlist (car (cdaddr (symbol-function 'foo))))
(nfn (length fnlist))
(ifn nil)
(bar-body '(addone x))
(i 0))
(eval (append
;; local symbol names
;; to which function definitions will be set
(list 'let (mapcar 'car fnlist))
;; set function definitions
(list '(while (< i nfn)
(setq ifn (nth i fnlist))
(eval `(fset ',(car ifn) ,(append (list 'lambda) (cdr ifn))))
(setq i (1+ i))))
;; function invocation
(list bar-body)))))
功能应用程序:
(foo 1) ;;=> 3
(bar 1) ;;=> 2
(addone 1) ;;=> 2 ?should not be defined outside of bar?
答案 0 :(得分:2)
这不是独立的,所以它不是一个真正的答案;但它与你提到的其他选项不同,所以无论如何我都会添加它。
(defmacro with-foo-functions (&rest forms)
`(flet ((addone (x) (1+ x))
(addtwo (x) (+ 2 x)))
,@forms))
(defun foo (x)
(with-foo-functions
(addtwo x)))
(defun bar (x)
(with-foo-functions
(addone x)))
答案 1 :(得分:1)
Emacs Lisp具有动态绑定功能。这与几乎所有其他Lisps使用的词法绑定不同。例如,如果您尝试在Common Lisp中执行以下操作,则会收到一条错误消息,指出FOO
未定义:
(defun bar ()
(foo 10))
(flet ((foo (x) (1+ x)))
(bar))
然而,在Emacs Lisp中,由于FOO是动态绑定的,因此FOO
中BAR
的绑定可用,因此返回11。
Emacs Lisp不为函数提供词法绑定,所以为了在Emacs Lisp中实现相同的功能,你必须通过将lambda绑定到词法变量来伪造它,然后使用宏来隐藏{{1 }}:
FUNCALL
此问题的另一个答案建议使用宏而不是(lexical-let ((foo #'(lambda (x) (1+ x))))
(macrolet ((foo (x) `(funcall foo ,x)))
(foo 10)))
。这有效,但会导致不必要的代码重复。我的解决方案可以防止这种情况,因为每次要调用函数时都必须编写flet
部分或使用macrolet
。如果这是经常需要的东西,可以写一个宏来将所有这些包装在词法funcall
版本中。