可以使用语法参数来代替语法吗? [英] Can syntax parameters be used to replace syntax?

查看:75
本文介绍了可以使用语法参数来代替语法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用语法参数,以便在需要注入新语法的地方注入新语法.然后将其结果用于其他语法. 但是,它没有按我预期的那样工作.这是一个最小的工作示例:

I'm trying to use syntax parameters in order to inject new syntax where I need it to be injected. The result of this is then used in other syntax. However, it's not working as I expect it to. Here's a minimal working example:

(require racket/stxparam)
(require (for-syntax racket/stxparam))

;; declare parameter to be replaced with code
(define-syntax-parameter placeholder
  (lambda (stx)
    (raise-syntax-error
     (syntax-e stx)
     "can only be used inside declare-many-commands")))

;; this is just to print what 'arg' looks like
(define-syntax (print-syntax stx)
  (syntax-case stx ()
    [(_ arg)
     #'(displayln 'arg)]))

;; this is the top-level entity invoked to produce many commands
(define-syntax-rule (declare-many-commands cmds)
  (begin
    (let ([X 10])
      (syntax-parameterize
       ([placeholder (make-rename-transformer #'X)])
       cmds))
    (let ([X 20])
      (syntax-parameterize
       ([placeholder (make-rename-transformer #'X)])
       cmds))))

(declare-many-commands
 (print-syntax placeholder))

运行此程序后,我希望得到的结果是:

What I would like to get as result when running this is:

10
20

但是我得到的是:

placeholder
placeholder

发布了一个新问题来解决该问题:在编译时使用Racket的语法参数注入语法吗?

Posted a new question to refine the problem: Injecting syntax at compile time using Racket's syntax parameters?

推荐答案

这里的问题是您的print-syntax宏引用了它的输入,而到宏转换器的输入是未扩展的语法.这意味着(print-syntax placeholder)的扩展将始终为(displayln 'placeholder),并且在quote下不会发生宏扩展,因此范围内的placeholder绑定是无关紧要的.

The problem here is that your print-syntax macro quotes its input, and inputs to macro transformers are unexpanded syntax. This means that the expansion of (print-syntax placeholder) will always be (displayln 'placeholder), and no macroexpansion ever occurs under quote, so the placeholder binding in scope is irrelevant.

如果要使用语法参数,则需要实际生成对placeholder绑定的引用.在这种情况下,您只需要删除quote的使用即可.您可以将print-syntax更改为(displayln arg),但是到那时,print-syntax确实没有理由成为宏,因为它等同于displayln函数.只需使用它即可:

If you want to use the syntax parameter, you need to actually produce a reference to the placeholder binding. In this case, you just need to remove the use of quote. You could change print-syntax to (displayln arg), but at that point, there’s really no reason for print-syntax to be a macro, since it’s equivalent to the displayln function. Just use that instead:

(declare-many-commands
 (displayln placeholder))

这将按您期望的方式打印1020.

This will print 10 and 20 as you expect.

您可能确实需要quote,但我不明白您的问题.但是,在那种情况下,我认为如果没有其他上下文,我很难理解您的意思.

It’s possible you really do want the quote, and I don’t understand your question. In that case, though, I think it’s difficult for me to understand what you’re getting at without some additional context.

这篇关于可以使用语法参数来代替语法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆