如何控制Scheme宏扩展的顺序? [英] How to control order of Scheme macro expansion?
问题描述
我用球拍宏延长
I'm working with the Racket macro extension syntax-id-rules
, that some other Scheme implementations provide under the name identifier-syntax
. These let you specify macro expansions that will happen even when the defined identifier isn't in head position. So for example:
(define hidden #f)
(define-syntax proxy
(syntax-id-rules (set!)
[(set! proxy v) (set! hidden v)]
[proxy hidden]))
将建立所述标识符
will set up the identifier proxy
to be a proxy for hidden
. This is a useless example, but it illustrates the usage.
我发现自己在想一个全球性的宏观普通的情况,我们称之为<4>,我想在那里我使用的标识符宏象
I find myself in a situation where I want a global ordinary macro, let's call it foo
, that I want to override in some cases where I'm using an identifier macro like proxy
. That is, I want to be able to do something like this:
(define-syntax foo
(syntax-rules ()
[(foo arg ...) 'default]))
(define hidden #f)
(define-syntax proxy
(syntax-id-rules (foo set!)
[(foo proxy arg ...) 'special]
[(set! proxy v) (set! hidden v)]
[proxy hidden]))
(foo proxy) ; should return 'special
但事实上最后一行返回<6>,因为<4>宏获取
But in fact the last line returns 'default
, because the foo
macro gets expanded before the proxy
one.
有什么想法可以实现这些目标,但是proxy
标识符宏会覆盖foo
的默认宏定义吗?我不致力于上述架构具体
Any ideas how I might achieve something along these lines, but with the proxy
identifier macro overriding the default macro definition for foo
? I'm not committed to the above architecture specifically.
添加:这不是用于任何实际使用,而是形式语义中理论观点的一部分演示.
Added: This isn't for any real-world usage, but part of a demonstration of a theoretical point in formal semantics.
推荐答案
@soegaard完美解释它.你不能这样做,你直接想要的东西,而无需修改宏扩展.
@soegaard explained it perfectly. You can't do what you want directly without modifying the macro expander.
要延长@ soegaard的答案,这里是模拟你所要求的一种方式.它本质上执行双调度"宏扩展.作为soegaard指出虽然,有可能是一个更地道的方式来实现你想要什么,这取决于你的目标.
To extend @soegaard's answer, here is a way to simulate what you are asking for. It essentially does a "double-dispatch" macro expansion. As soegaard noted though, there's probably a more idiomatic way to achieve what you want, depending on your goals.
#lang racket
(require (for-syntax syntax/parse))
(begin-for-syntax
(define (special-condition? id)
(and (identifier? id)
(regexp-match #rx"^p" ; starts with "p"
(symbol->string (syntax->datum id))))))
(define-syntax foo
(syntax-parser
[(_ special-case arg ...)
#:when (special-condition? #'special-case)
#'(special-case 'hidden-special-case-tag arg ...)]
; else
[(_ arg ...) #''default]))
(define hidden #f)
(define-syntax proxy
(syntax-id-rules (quote set!)
[(proxy (quote hidden-special-case-tag) arg ...) 'special]
[(set! proxy v) (set! hidden v)]
[(proxy arg ...) 'other]
[proxy hidden]))
(foo non-proxy) ; => 'default
(foo proxy) ; => 'special
(proxy) ; => 'other
proxy ; => #f
(set! proxy #t)
proxy ; => #t
这篇关于如何控制Scheme宏扩展的顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!