Macros 这个Racket宏是用惯用的风格编写的吗?

Macros 这个Racket宏是用惯用的风格编写的吗?,macros,racket,Macros,Racket,我的儿子和我正在一起学习球拍,并正在建立一个非常简单的基于文本的冒险,直接从REPL使用。例如,玩家可以键入(转到“北)或(以“苹果”为例) 在一些基本的东西开始工作后,我儿子认为引用这个名词有点痛苦(奇怪的是,帕伦夫妇并没有打扰他!),所以我们尝试了一下宏,我们确实做了一些工作,但它需要一个显式的函数和一个相应的宏,例如 (define (do-take item) ...) (define-syntax (take stx) (define item (cadr

我的儿子和我正在一起学习球拍,并正在建立一个非常简单的基于文本的冒险,直接从REPL使用。例如,玩家可以键入
(转到“北)
(以“苹果”为例)

在一些基本的东西开始工作后,我儿子认为引用这个名词有点痛苦(奇怪的是,帕伦夫妇并没有打扰他!),所以我们尝试了一下宏,我们确实做了一些工作,但它需要一个显式的函数和一个相应的宏,例如

    (define (do-take item) ...)
    (define-syntax (take stx)
      (define item (cadr (syntax->datum stx)))
      (datum->syntax stx `(do-take ',item)))
我想我们可以做得更好,所以我读了更多的东西,得出了以下结论:

    (require (for-syntax racket/syntax))
    (define-syntax (define-verb stx)
     (syntax-case stx ()
       [(_ (verb noun) body-first body-rest ...)
        (with-syntax ([verb-fun (format-id stx "do-~a" #'verb)])
          #'(begin
              (define-syntax-rule (verb noun) (verb-fun 'noun))
              (define (verb-fun noun) body-first body-rest ...)))]))
现在,我们可以编写
(定义动词(take item)…)
,REPL的播放器可以键入
(take apple)


我的问题是,考虑到我们想要实现的目标,这是一种合理的方法,还是有一种更简单/惯用的方法来实现同样的目标?

一般来说,我建议做的主要事情是使用库。它有更多的语法分析工具。您甚至可以使用一些表单,例如使宏更加简洁。使用
syntax/parse
重写代码(删除这一行,因为它似乎没有做任何事情),宏将如下所示:

#lang racket
(require syntax/parse/define
         (for-syntax syntax/parse racket/syntax))
(define-syntax-parser define-verb
  [(_ (verb:id noun) body ...+)
   (define/syntax-parse verb-fun (format-id stx "do-~a" #'verb))
   #'(begin
       (define-simple-macro (verb noun) (verb-fun 'noun))
       (define (verb-fun noun) body ...))])
这为您提供了一些比您给出的示例更好的东西:

  • :id
    确保动词
    是文字标识符,而不是表达式
  • …+
    表示您只需要一个
    主体
    模式,而不是两个
  • 使用
    define/syntax parse
    意味着您的代码不会比使用syntax
    缩进更多。(尽管这是一个偏好问题。)

语法引号需要在
开始时
使用
定义语法规则
才能使宏工作。我很难理解您在这里说的话。您评论说不确定
定义语法规则
的用途。它应该在一个
#'(begin…
中。对不起,我不清楚!啊,好的。在这种情况下,我会相应地更新我的答案(和问题)。谢谢。:)