为什么不能定义名称为“if”的Scheme宏?

问题描述 投票:0回答:1

这是一个非常简单的Scheme宏,可以在MIT/GNU Scheme 12.1上运行:

1 ]=> (define-syntax example
        (syntax-rules () 
          ((_) 'ok)))

;Value: example

1 ]=> (example)

;Value: ok

但是,使用名称

if
定义相同的宏会产生错误:

1 ]=> (define-syntax if
        (syntax-rules () 
          ((_) 'ok)))

;Premature reference to reserved name: if
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.

我以前从未使用过Scheme宏,但我的印象是Scheme没有“保留”名称,并且Scheme中的任何名称都可以重新定义。事实上,将

if
重新定义为正常程序可以按预期工作:

1 ]=> (define (if) 'ok)

;Value: if

1 ]=> (if)

;Value: ok

我浏览了参考手册中有关宏的部分(https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-ref/Macros.html),但我不能'找不到问题的原因。

是否有

syntax-rules
的内部操作导致此失败?

更新1

使用

if
本地重新定义
let-syntax
有效:

1 ]=> (let-syntax ((if (syntax-rules () ((_) 'ok))))
        (if))

;Value: ok

我仍然不确定为什么

define-syntax
不起作用。

更新2

可以使用宏隐藏其他内置关键字:

1 ]=> (define-syntax define (syntax-rules () ((_) 'ok)))

;Value: define

1 ]=> (define)

;Value: ok

1 ]=> (define-syntax set! (syntax-rules () ((_) 'ok)))

;Value: set!

1 ]=> (set!)

;Value: ok

1 ]=> (define-syntax lambda (syntax-rules () ((_) 'ok)))

;Value: lambda

1 ]=> (lambda)

;Value: ok

1 ]=> (define-syntax cond (syntax-rules () ((_) 'ok)))

;Value: cond

1 ]=> (cond)

;Value: ok

有趣的是,你甚至可以重新定义

define-syntax

1 ]=> (define-syntax define-syntax (syntax-rules () ((_) 'ok)))

;Value: define-syntax

1 ]=> (define-syntax)

;Value: ok

但是,尝试重新定义关键字

syntax-rules
会遇到与重新定义
if
类似的错误(注意:我启动了一个新的 REPL,因为最后一个宏被遮蔽了
define-syntax
):

1 ]=> (define-syntax syntax-rules (syntax-rules () ((_) 'ok)))

;Premature reference to reserved name: syntax-rules
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.
macros scheme reserved-words mit-scheme syntax-rules
1个回答
0
投票

if
can 在许多Scheme 实现中被定义为顶层的宏。我测试过

 (define-syntax if
        (syntax-rules () 
          ((_) 'ok)))
(ok) ; returns 'ok

关于 Guile 3.0.9、Chicken 5.3.0、Gauche 0.9.9、Chibi 0.10.0(以 git 最新版本的形式)、Chez 9.6.2、Gambit 4.9.5、Kawa 3.1.1 和 MIT/ GNU 方案 11.2。所有人都接受并运行代码,没有错误。您说您正在使用 MIT/GNU 方案 12.1,因此两个版本之间的某些更改是有原因的。

有趣的是,

syntax-rules
的重新定义给出了11.2中的错误。 Guile、Chicken、Gauche、Chibi 和 Gambit 都接受了,而 Chez 和 Kawa 则抛出了错误。

© www.soinside.com 2019 - 2024. All rights reserved.