2009-03-19 20 views
10

tengo el siguiente códigofunciones elisp como parámetros y como valor de retorno

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

Una llamada

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

declaraciones de 55,0 (el valor correcto) en SBCL pero se estrella con la siguiente pila en 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) 

¿Cómo puedo hacer que funcione en Emacs lisp?

Respuesta

12

Una pregunta engañosa, pero finalmente conseguí esto resuelto. El problema es que #' en la definición de avg-damp hace que el compilador compile la función lambda en el momento cuando se compila el propio avg-damp, antes de que se conozca el valor real de f. Es necesario retrasar la compilación de esta función en un punto posterior en el tiempo, cuando avg-húmeda se llama, así:

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

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

Backquoting hace el truco.

Editar: Por supuesto, todo el problema desaparece si se define avg-húmedo en una forma uncurried, como este:

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

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

Pero supongo que tienes tus razones para no hacerlo.

19

Este estilo de programación no funciona en simple Emacs Lisp. Emacs Lisp utiliza un enlace dinámico e idiomas como Scheme y Common Lisp utilizan el enlace léxico. Tu código expone la diferencia. Ver: Extent in Emacs Lisp

Vea también esta pregunta: How do I do closures in Emacs Lisp? y la 'solución' con lexical-let. lexical-let es una extensión para Emacs Lisp en el paquete "cl".

Ver también: desde Emacs 24.1 hay opcional lexical binding. Aprenda cómo usarlo: using lexical binding.

Cuestiones relacionadas