Racket中的宏定义宏?

时间:2014-10-27 21:15:57

标签: macros lisp common-lisp racket hygiene

在Common Lisp中,创建宏定义宏相对容易。例如,以下宏

(defmacro abbrev (short long)
  `(defmacro ,short (&rest args)
     `(,',long ,@args)))

是一个宏定义宏,因为它扩展到另一个宏。

如果我们现在提出

(abbrev def defun) 

在我们的程序中,每当我们定义一个新函数时,我们都可以编写def而不是defun。 当然,abbrev也可以用于其他事情。例如,在

之后
(abbrev /. lambda)

我们可以写(/. (x) (+ x 1))而不是(lambda (x) (+ x 1))。尼斯。 (有关缩写的详细说明,请参阅http://dunsmor.com/lisp/onlisp/onlisp_20.html

现在,我的问题是:

  1. 我可以在Racket中编写宏定义宏吗?
  2. 如果可以,怎么办? (例如,如何写类似的东西 Racket中的abbrev宏?)

3 个答案:

答案 0 :(得分:8)

根据“球拍指南”的this部分:

(define-syntax-rule (abbrev short long)
  (define-syntax-rule (short body (... ...))
    (long body (... ...))))

引用上述链接:

  

其定义中唯一不明显的部分是(......),其中   “引用”......因此它在生成的宏中扮演其通常的角色,   而不是生成宏。

现在

(abbrev def define)
(abbrev /. lambda) 
(def f (/. (x) (+ x 1)))
(f 3)  

产量

4

FWIW,它也适用于Guile,所以它没有特定于Racket的东西。

答案 1 :(得分:5)

ad 1.是的。 广告2.您的示例最容易编写

#lang racket

(define-syntax (abbrev stx)
  (syntax-case stx ()
    [(_ short long)
     #'(define-syntax short (make-rename-transformer #'long))]))

(abbrev def define)
(def x 42)
x

上面的示例评估为42。

答案 2 :(得分:0)

我发现只需使用define或let语句即可重命名:

(define =? =)
(define lr list-ref)

或:

(let ((=? =)
      (lr list-ref))
  (println (lr '(1 2 3) 2))
  (println (=? 1 2))
  (println (=? 1 1)))

输出:

3
#f
#t

似乎没有必要为此目的使用任何宏。