在Common Lisp中重命名lambda

时间:2012-03-04 18:06:28

标签: macros lambda common-lisp

我最近开始学习Common Lisp,并且(只是为了好玩)决定重命名lambda宏。

我的尝试是这样的:

> (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:

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

编辑2: 使其运作的一种方法(如Rainer所建议):

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

(在Clozure CL中测试)

3 个答案:

答案 0 :(得分:20)

在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代码看起来更像Scheme代码,然后没有必要编写

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

使用LAMBDA宏我们可以写

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

您的示例失败,因为

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

无效的Common Lisp语法。

Common Lisp要求

  • 数据对象
  • 变量
  • (function args...)
  • 形式的函数调用
  • ((lambda (arglist ...) body) args...)
  • 形式的函数调用
  • (macro-name forms...)
  • 这样的宏观形式
  • 使用其中一个内置特殊运算符的特殊表单,例如FUNCTIONLET,... 在Common Lisp中的special operators列表中定义

正如您可以看到

的语法
((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))

答案 1 :(得分:2)

您可能还认为LAMBDA是一个运算符,给定一个术语和一个自由变量列表,它返回一个函数。这个p.o.v.将LAMBDA从基本函数和基本宏的系列中取出 - 至少就解释器而言。

答案 2 :(得分: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 _))

也许更简洁,只有一个_ _