【问题标题】:Macro-defining macro in Racket?在 Racket 中定义宏?
【发布时间】:2014-12-23 04:29:35
【问题描述】:

在 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. 如果可以,该怎么做? (例如,如何编写类似于 abbrev Racket 中的宏?)

【问题讨论】:

  • 你颠倒了你的宏参数,long 应该是第一位的。
  • 我在我的问题中更正了这一点。坦克!

标签: macros lisp common-lisp racket hygiene


【解决方案1】:

根据球拍指南的this 部分:

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

引用以上链接:

其定义中唯一不明显的部分是 (... ...),它 “quotes” ...以便它在生成的宏中发挥其通常的作用, 而不是生成宏。

现在

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

产量

4

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

【讨论】:

    【解决方案2】:

    广告 1. 是的。 ad 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。

    【讨论】:

    • “新”术语在这里造成混乱(“短”实际上是新术语)。如果在此页面上的其他地方使用“long”(而不是“new”)会更清楚。
    • 我同意。我已经改了。
    【解决方案3】:

    我发现重命名可以简单地使用 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
    

    为此目的似乎不需要任何宏。

    【讨论】:

    • 当你想重命名一个特殊的表单或一个像definelambda这样的宏时,这不起作用
    • 那么有效的是(define-syntax def (make-rename-transformer #'define))(define-syntax /. (make-rename-transformer #'lambda))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多