首页 文章

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

提问于
浏览
2

我的儿子和我正在一起学习球拍,正在构建一个非常简单的基于文本的冒险,可直接从REPL中使用 . 因此,例如,玩家可以输入 (go 'north)(take 'apple) .

在得到一些基本的东西工作后,我的儿子认为引用名词有点痛苦(奇怪的是,parens不打扰他!),所以我们用宏攻击了一下,我们确实得到了一些工作但是它需要一个显式函数和一个相应的宏,例如

(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 ...)))]))

所以现在,我们可以写 (define-verb (take item) ...) ,REPL的播放器可以输入 (take apple) .

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

1 回答

  • 1

    一般来说,我建议做的主要是使用syntax/parse库 . 它有更多用于解析语法的工具 . 你甚至可以使用像define-syntax-parser这样的表格来使你的宏更简洁 . 使用 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 确保 verb 是文字标识符,而不是表达式 .

    • ...+ 表示您只需要一个 body 模式,而不是两个 .

    • 使用 define/syntax-parse 表示您的代码没有比 with-syntax 更多缩进 . (虽然这是一个偏好的问题 . )

相关问题