在Racket中定义宏定义的宏?

7
在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))。很好。(有关abbrev的详细解释,请参见http://dunsmor.com/lisp/onlisp/onlisp_20.html)
现在,我的问题是:
  1. 我能否在Racket中编写宏定义宏?
  2. 如果可以,如何实现?(例如,如何编写类似于abbrev宏的东西?)

你颠倒了宏参数,应该先放long。 - uselpa
我在我的问题中进行了更正。谢谢! - Racket Noob
3个回答

9
根据 Racket Guide 的 这部分 内容:
(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特有的东西。


5

广告 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。


“new”这个术语在这里造成了混淆(实际上,“short”才是新术语)。如果像页面其他地方一样使用“long”(而不是“new”),会更清晰明了。 - rnso
我同意。我已经修改了它。 - soegaard

0

我发现重命名可以通过定义或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

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


当你想重命名特殊形式或宏,如definelambda时,那样做是行不通的。 - Alex Knauth
那么有效的是(define-syntax def (make-rename-transformer #'define))或者(define-syntax /. (make-rename-transformer #'lambda)) - Alex Knauth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接