2012-03-04 18 views
11

Empecé a aprender Common Lisp recientemente, y (solo por diversión) decidí cambiar el nombre de la macro lambda.Renombrando lambda en Common Lisp

Mi intento fue la siguiente:

> (defmacro λ (args &body body) `(lambda ,args ,@body)) 

Parece expandir correctamente cuando por sí mismo:

> (macroexpand-1 '(λ (x) (* x x))) 
(LAMBDA (X) (* X X)) 

Pero cuando está anidada dentro de una expresión, la ejecución falla:

> ((λ (x) (* x x)) 2) 
(Λ (X) (* X X)) is not a function name; try using a symbol instead 

Probablemente me esté perdiendo algo obvio sobre la expansión macro, pero no pude descubrir qué es.

¿Quizás me pueda ayudar?

edición: No funciona con lambda:

> ((lambda (x) (* x x)) 2) 
4 

editar 2: Una forma de hacerlo funcionar (según lo sugerido por Rainer):

> (set-macro-character #\λ (lambda (stream char) (quote lambda))) 

(probado en Clozure CL)

Respuesta

20

En Common Lisp LAMBDA hay dos cosas diferentes: una macro y un símbolo que se pueden usar en una expresión LAMBDA. expresión

El LAMBDA:

(function (lambda (x) (foo x))) 

más corto escrito como

#'(lambda (x) (foo x)) 

un Applied expresión lambda también es válido:

((lambda (x) (+ x x)) 4) 

Por encima de ambas formas son parte de la sintaxis núcleo de Common Lisp.

Final en la definición de Common Lisp se ha agregado una macro llamada LAMBDA. Es bastante confuso, pero con buenas intenciones. ;-) Está documentado como Macro LAMBDA.

(lambda (x) (+ x x)) 

se expande en

(function (lambda (x) (+ x x)) 

Hace código de Common Lisp mirada un poco más como código de Scheme y entonces no es necesario escribir

(mapcar #'(lambda (x) (+ x x)) some-list) 

Con la LAMBDA macro podemos escribir

(mapcar (lambda (x) (+ x x)) some-list) 

Su ejemplo falla porque

((my-lambda (x) (* x x)) 2) 

sintaxis no es válida Common Lisp.

Common Lisp espera ya sea

  • un objeto de datos
  • una variable
  • una llamada de función en forma (function args...)
  • una llamada de función en forma ((lambda (arglist ...) body) args...)
  • una forma macro como (macro-name forms...)
  • una forma especial usando uno de los operadores especiales integrados l ike FUNCTION, LET, ... definido en la lista de special operators en Common Lisp

Como se puede ver una sintaxis de

((macro-name forms...) forms...) 

no es una parte de Common Lisp.

Es posible leer el carácter λ como LAMBDA:

(defun λ-reader (stream char) 
    (declare (ignore char stream)) 
    'LAMBDA) 

(set-macro-character #\λ #'λ-reader) 

Ejemplo:

CL-USER 1 > ((λ (x) (* x x)) 3) 
9 

CL-USER 2 > '(λ (x) (* x x)) 
(LAMBDA (X) (* X X)) 
+2

No es la 'función' en la expansión de' lambda' que es un problema, es el comportamiento de las aplicaciones con '' lambda'. Entonces, en su explicación, cambiaría: "Una expresión lambda aplicada también es válida" en "Una expresión lambda aplicada" también es válida (solo para 'lambda' y no para macros que se expanden a ella)". –

+0

¡Tiene sentido ahora, gracias! Entonces, ¿no hay forma de obtener (λ ...) para emular una expresión lambda? – ibab

+3

@qrl: la sintaxis ((λ (x) ...) 4) es posible con una macro de lectura en implementaciones de CL que admiten ese carácter. El lector de Lisp tendría que expandir λ a LAMBDA. –

2

También podría pensar en LAMBDA como un operador que, dado un plazo y una lista de libres variables, devuelve una función. Este p.o.v. saca a LAMBDA de la familia de funciones básicas y macros elementales, al menos en lo que respecta al intérprete.