Переименование лямбды в Common Lisp

Недавно я начал изучать Common Lisp, и (просто для удовольствия) решил переименовать лямбда-макрос.

Моя попытка:

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

Кажется, он правильно расширяется, когда сам по себе:

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

Но когда он вложен внутри выражения, выполнение не выполняется:

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

Мне, вероятно, не хватает чего-то очевидного о расширении макросов, но не могу понять, что это такое.

Может быть, вы можете мне помочь?

изменить: Он работает с лямбдой:

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

изменить 2: Один из способов заставить его работать (как предложил Райнер):

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

(проверено в Clozure CL)

Ответ 1

В Common Lisp LAMBDA есть две разные вещи: макрос и символ, который может использоваться в выражении LAMBDA.

Выражение LAMBDA:

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

короче написано как

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

Применяется также lambda выражение:

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

Выше обе формы являются частью основного синтаксиса Common Lisp.

Позднее в определении Common Lisp добавлен макрос с именем LAMBDA. Достаточно смешно, но с благими намерениями.;-) Это задокументировано как Macro LAMBDA.

(lambda (x) (+ x x))

расширяется в

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

Это делает код Common Lisp немного похож на код схемы, и тогда нет необходимости писать

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

С макросом LAMBDA мы можем написать

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

Ваш пример не работает, потому что

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

недействителен. Общий синтаксис Lisp.

Общий Lisp ожидает либо

  • объект данных
  • переменная
  • вызов функции в форме (function args...)
  • вызов функции в форме ((lambda (arglist ...) body) args...)
  • макроформа, подобная (macro-name forms...)
  • специальную форму с использованием одного из встроенных специальных операторов, таких как FUNCTION, LET,... определенном в списке специальных операторов в Common Lisp

Как вы можете видеть синтаксис

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

не является частью Common Lisp.

Можно прочитать символ λ как LAMBDA:

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

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

Пример:

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

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

Ответ 2

Вы также можете думать о LAMBDA как о операторе, который, учитывая член и список свободных переменных, возвращает функцию. Это p.o.v. выводит LAMBDA из семейства базовых функций и элементарных макросов - по крайней мере, в том, что касается интерпретатора.