2010-04-17 11 views
22

Estoy haciendo algunas llamadas tediosas a un conjunto de funciones, pero los parámetros se determinarán en tiempo de ejecución. Escribí una función simple para mantener mi código SECO, pero darle un nombre es innecesario. No uso esta función en ningún otro lado.Cómo crear una función temporal en Emacs Lisp

Estoy tratando de hacerlo de la manera que lo haría en el esquema, pero me da un error de void-function:

(let ((do-work (lambda (x y z) 
        (do-x x) 
        (do-y y) 
        ;; etc 
       ))) 
    (cond (test-1 (do-work 'a 'b 'c)) 
     (test-2 (do-work 'i 'j 'k)))) 

pude pegar todo en un apply (por ejemplo, (apply (lambda ...) (cond ...))) pero que no es muy legible ¿Hay una mejor manera?

Respuesta

27

Al igual que otros lisps (pero no Scheme), Emacs Lisp tiene espacios de nombres separados para variables y funciones (es decir, es ‘Lisp2’, not a ‘Lisp1; ver Technical Issues of Separation in Function Cells and Value Cells para el origen y el significado de estos términos).

Tendrá que usar funcall o apply para llamar a una lambda (u otra función) que esté almacenada en una variable.

(cond (test-1 (funcall do-work 'a 'b 'c)) 
     (test-2 (funcall do-work 'i 'j 'k)) 

Uso funcall si siempre va a enviar el mismo número de argumentos. Use apply si necesita poder enviar una cantidad variable de argumentos.

El mecanismo interno es que cada símbolo tiene multiple “cells”. Qué celda se utiliza depende de where the symbol is in an evaluated form. Cuando un símbolo es el primer elemento de un formulario evaluado, its “function” cell is used. En cualquier otra posición, its “value” cell is used. En su código, do-work tiene la función en su celda de valor. Para acceder a ella como una función, usa funcall o apply. Si estuviera en la celda de función, podría llamarlo directamente usando su nombre como el carro de una forma evaluada. Puede lograr esto con flet or labels from the cl package.

21

hacer (require 'cl) para tirar en el paquete Common Lisp, a continuación, utilizar flet en lugar de let:

(flet ((do-work (x y z) 
      (do-x x) 
      (do-y y) 
      ;; etc 
     )) 
    (cond (test-1 (do-work 'a 'b 'c)) 
     (test-2 (do-work 'i 'j 'k)))) 
+2

+1. Realmente no me gustan los Lisp-2. – progo

4

Usted puede hacer esto de la manera ANSI Common Lisp (aunque creo que hay algunas devels Emacs que le dará miradas desagradables):?

(flet ((do-work (x y z) 
       (do-x x) 
       (do-y y) 
       ;; etc 
       )) 
    (cond (test-1 (do-work 'a 'b 'c)) 
     (test-2 (do-work 'i 'j 'k)))) 

No sé si usted primero tiene que (require 'cl) (o cl-macs) para utilizar flet. Si desea definir funciones recursivas, necesitará usar labels IIRC.

Cuestiones relacionadas