Renaming lambda in Common Lisp
Asked Answered
N

3

12

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)

Nineveh answered 4/3, 2012 at 18:6 Comment(0)
F
21

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))
Felty answered 4/3, 2012 at 18:31 Comment(4)
It's not the function in the expansion of lambda that is a problem, it's the hard-wired behavior of function applications with lambda. So in your explanation I'd change: "An applied lambda expression is also valid" into "An applied lambda expression is also valid (only for lambda and not for macros that expand to it)".Raines
It makes sense now, thanks! So there's no way to get (λ ...) to emulate a lambda expression?Nineveh
@qrl: the ((λ (x) ...) 4) syntax is possible with a read-macro in CL implementations which support that character. The Lisp reader would have to expand λ into LAMBDA.Felty
Awesome, looks like a good opportunity to get into read-macros.Nineveh
P
2

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.

Peel answered 12/10, 2012 at 3:5 Comment(0)
A
0
(defun lambda-char (stream char)
  "A lambda with only ONE arg _"
  (declare (ignore char))
  (let ((codes (read stream nil)))
    `(lambda (_) ,codes)))

(set-macro-character #\λ #'lambda-char t)   
λ(+ 1 2 _) ; => (lambda (_) (+ 1 2 _))

Maybe this is more concise, with ONLY ONE arg of _

Adah answered 19/4, 2020 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.