计划中的匿名宏

时间:2013-02-03 09:22:23

标签: compiler-construction macros functional-programming lisp scheme

我最近正在学习计划并对设计感到好奇,因为没有标识符就无法评估宏,而lambda(程序)可以这样做。

例如,我可以使用匿名lambda:

((lambda x x) 1 2 3)

似乎我必须使用以下语法定义宏:

(define-macro my-macro (lambda x x))

我很好奇为什么这样的方法会像这样直接创建一个宏:

(define my-macro (macro-lambda x x))

我想如果将宏和lambda视为不同的类型,第二个可能更优雅。

我的问题是:

  1. define-macro做什么?
  2. 宏和lambda之间的根本区别是什么?
  3. 是否有方案中的匿名宏,如果没有,为什么?

2 个答案:

答案 0 :(得分:5)

首先举例说明如何模拟"匿名宏"。 然后我会对有用性发表评论。

考虑这个匿名宏变换器, 它采用表示数字的语法对象 并返回一个新的语法对象表示 输入数字的两倍。

(λ (stx) 
  (datum->syntax stx
    (* 2 (syntax->datum stx))))

我们可以这样测试:

> ((λ (stx) 
    (datum->syntax stx
      (* 2 (syntax->datum stx))))
  #'3)

结果是一个带有6的语法对象。

如果我们想要实际的数字6,我们可以使用eval

> (eval ((λ (stx) 
          (datum->syntax stx
            (* 2 (syntax->datum stx))))
        #'3))
6

现在我们使用了匿名语法转换器来重写 3成6。

匿名宏有用吗?

匿名函数用于你函数的地方, 但你只需要一次。如果是相同的匿名函数 在程序中使用两次,最好给它一个名字, 然后只是两次引用它。

语法转换的情况也是如此。如果你需要的话 相同的转换至少两次,你应该给它一个名字。 匿名语法转换唯一有意义的时候 是,如果只使用一次。在大多数情况下,它会更简单 只是为了写出转换的结果。我无法思考 例如,匿名转换会产生 事情比较简单。

注意:所有示例都在Racket中进行了测试。

答案 1 :(得分:0)

宏在编译时转换树,而其余代码在运行时执行。

通常,两个操作(宏扩展和lisp代码执行)都是在列表上工作的过程。即对于宏和程序,lambda没有根本的区别,它只是执行它们的时间。这意味着会出现一些其他问题,例如命名等。

(define ..)在运行时执行,因此我认为你的建议不会真正起作用。

因此,defmacro语法清楚地表明宏是一个普通函数,但在编译时进行了评估。 macro-lambda宁愿暗示这一点。