elisp functions as parameters and as return value

柔情痞子 提交于 2019-11-29 18:27:08

问题


I have the following code

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

A call

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

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)

How can I make it work in Emacs lisp?


回答1:


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.

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.




回答2:


This style of programming does not work in plain Emacs Lisp. Emacs Lisp uses dynamic binding and languages like Scheme and Common Lisp are using lexical binding. Your code exposes the difference. See: Extent in Emacs Lisp

See also this question: How do I do closures in Emacs Lisp? and the 'solution' with lexical-let. lexical-let is an extension for Emacs Lisp in the "cl" package.

See also: since Emacs 24.1 there is optional lexical binding. Learn how to use it: using lexical binding.



来源:https://stackoverflow.com/questions/661490/elisp-functions-as-parameters-and-as-return-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!