Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Renaming lambda in Common Lisp

I started learning Common Lisp recently, and (just for fun) decided to rename the lambda macro.

My attempt was this:

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

It seems to expand correctly when by itself:

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

But when it's nested inside an expression, execution fails:

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

I am probably missing something obvious about macro expansion, but couldn't find out what it is.

Maybe you can help me out?

edit: It does work with lambda:

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

edit 2: One way to make it work (as suggested by Rainer):

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

(tested in Clozure CL)

like image 297
ibab Avatar asked Mar 04 '12 18:03

ibab


2 Answers

In Common Lisp LAMBDA is two different things: a macro and a symbol which can be used in a LAMBDA expression.

The LAMBDA expression:

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

shorter written as

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

An applied lambda expression is also valid:

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

Above both forms are part of the core syntax of Common Lisp.

Late in the definition of Common Lisp a macro called LAMBDA has been added. Confusingly enough, but with good intentions. ;-) It is documented as Macro LAMBDA.

(lambda (x) (+ x x))

expands into

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

It makes Common Lisp code look slightly more like Scheme code and then it is not necessary to write

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

With the LAMBDA macro we can write

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

Your example fails because

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

is not valid Common Lisp syntax.

Common Lisp expects either

  • a data object
  • a variable
  • a function call in the form (function args...)
  • a function call in the form ((lambda (arglist ...) body) args...)
  • a macro form like (macro-name forms...)
  • a special form using one of the built-in special operators like FUNCTION, LET, ... defined in the list of special operators in Common Lisp

As you can see a syntax of

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

is not a part of Common Lisp.

It is possible to read the character λ as LAMBDA:

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

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

Example:

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

CL-USER 2 > '(λ (x) (* x x))
(LAMBDA (X) (* X X))
like image 78
Rainer Joswig Avatar answered Nov 02 '22 02:11

Rainer Joswig


You might also think of LAMBDA as an operator which, given a term and a list of free variables, returns a function. This p.o.v. takes LAMBDA out of the family of basic functions and elementary macros -- at least as far as the interpreter is concerned.

like image 43
wrstark Avatar answered Nov 02 '22 00:11

wrstark