elisp函数作为参数和返回值 [英] elisp functions as parameters and as return value
问题描述
我有以下代码
(defun avg-damp(f)
#'(lambda(x) (/ (+ (funcall f x) x) 2.0)))
通话
(funcall (avg-damp #'(lambda(v) (* v v))) 10)
在SBCL中返回55.0(正确的值),但在emacs lisp中的以下堆栈崩溃
returns 55.0 (the correct value) in SBCL but crashes with the following stack in emacs lisp
Debugger entered--Lisp error: (void-variable f)
(funcall f x)
(+ (funcall f x) x)
(/ (+ (funcall f x) x) 2.0)
(lambda (x) (/ (+ ... x) 2.0))(10)
funcall((lambda (x) (/ (+ ... x) 2.0)) 10)
eval((funcall (avg-damp (function ...)) 10))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)
如何使其在Emacs Lisp中工作?
How can I make it work in Emacs lisp?
推荐答案
一个棘手的问题,但终于明白了.问题在于,avg-damp定义中的#'
使编译器在编译avg-damp本身时在已知f的实际值之前编译lambda函数.您需要将该函数的编译延迟到以后的某个时间点,例如,在调用avg-damp 时,如下所示:
A tricky question, but finally got this figured out. The problem is that #'
in the definition of avg-damp makes the compiler compile the lambda function at the time when avg-damp itself is compiled, before the actual value of f is known. You need to delay the compilation of this function to a later point in time, when avg-damp is called, like this:
(defun avg-damp (f)
`(lambda(x) (/ (+ (funcall ,f x) x) 2.0)))
(funcall (avg-damp #'(lambda(v) (* v v))) 10)
使用引号可以解决问题.
Backquoting does the trick.
编辑:当然,如果您以非咖喱形式定义avg-damp,那么整个问题就会消失,例如:
Edit: Of course, the whole problem goes away if you define avg-damp in an uncurried form, such as this:
(defun avg-damp (f x)
(/ (+ (funcall f x) x) 2.0))
(funcall 'avg-damp #'(lambda(v) (* v v)) 10)
但是我想您有理由不这样做.
But I guess you have your reasons not to do so.
这篇关于elisp函数作为参数和返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!