elisp函数作为参数和返回值 [英] elisp functions as parameters and as return value

查看:110
本文介绍了elisp函数作为参数和返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码

(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆