当前位置:  开发笔记 > 开发工具 > 正文

elisp用作参数和返回值

如何解决《elisp用作参数和返回值》经验,为你挑选了2个好方法。

我有以下代码

(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中与以下堆栈崩溃

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中使其工作?



1> Rainer Joswi..:

这种编程风格在普通的Emacs Lisp中不起作用.Emacs Lisp使用动态绑定,而Scheme和Common Lisp等语言正在使用词法绑定.您的代码暴露了差异.请参阅:Emacs Lisp中的范围

另请参阅此问题:如何在Emacs Lisp中执行闭包操作?和lexical-let的"解决方案".lexical-let是"cl"包中Emacs Lisp的扩展.

另请参见:因为Emacs 24.1有可选的词法绑定.学习如何使用它:使用词法绑定.



2> David Hanak..:

一个棘手的问题,但终于搞清楚了.问题在于#'avg-damp的定义使编译器在编译avg-damp本身时编译lambda函数,然后才知道f的实际值.当调用avg-damp时,您需要将此函数的编译延迟到稍后的时间点,如下所示:

(defun avg-damp (f)
   `(lambda(x) (/ (+ (funcall ,f x) x) 2.0)))

(funcall (avg-damp #'(lambda(v) (* v v))) 10)

反引用可以解决问题.

编辑:当然,如果你以一种未经处理的形式定义avg-damp,整个问题就会消失,例如:

(defun avg-damp (f x)
   (/ (+ (funcall f x) x) 2.0))

(funcall 'avg-damp #'(lambda(v) (* v v)) 10)

但我猜你有理由不这样做.

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有