如何控制Scheme宏扩展的顺序? [英] How to control order of Scheme macro expansion?

查看:99
本文介绍了如何控制Scheme宏扩展的顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用球拍宏延长工作,其他一些方案实施的名称下提供.这些让你指定展开宏时所定义的标识不是行头位置将发生连.例如:

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屋!

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