如何在 scm 方案中定义一个函数来测试其参数是不是为宏?
Posted
技术标签:
【中文标题】如何在 scm 方案中定义一个函数来测试其参数是不是为宏?【英文标题】:How to define a function in scm scheme that tests if its parameter is a macro?如何在 scm 方案中定义一个函数来测试其参数是否为宏? 【发布时间】:2021-01-22 15:18:43 【问题描述】:例如,假设 'match 是一个宏,而 'car 不是:
> (macro? 'match)
#t
> (macro? 'car)
#f
【问题讨论】:
【参考方案1】:大多数方案都没有这样的macro?
函数。要区分普通函数和宏,您可以使用 RnRS 中的procedure?
:
> (procedure? car)
#t
【讨论】:
这真的适用于宏吗?(procedure? let)
不是语法错误吗?
@FlorianWeimer 是的,您可能需要捕获错误。在 bigloo 中,您的示例报告 Unbound variable -- let
。
感谢您的帮助。也许现在是向您提供我提出这个问题的理由的好时机:几个月前,当我试图将 Andrew Wright 的 Softscheme 系统移植到现代方案(Bigloo、ChezScheme 或 Racket)时,我遇到了“宏?”他的源代码中的函数调用(从 90 年代初用 ChezScheme 编写)。显然,该功能在那些早期(专有)版本的 chezscheme 中。【参考方案2】:
问题是不能使用 Scheme 语法命名关键字:
> (procedure? let)
Exception: invalid syntax let
所以你必须使用一个符号,比如'let
,来引用它。鉴于eval
需要能够将关键字与其他标识符区分开来,您可以尝试以下操作:
(define keyword?
(lambda (symbol)
(guard (x [else (syntax-violation? x)])
(eval symbol)
#f)))
(keyword? 'let) ⇒ #t
(keyword? 'car) ⇒ #f
(keyword? 'does-not-exist) ⇒ #f
但这无疑是一把相当大的锤子。 eval
的这种单参数形式是 Chez Scheme 的扩展,提供 (interaction-environment)
作为默认环境。它也不是完全安全的,因为它会挂起:
(let-syntax ([foo (lambda (x) (raise "oops"))])
(keyword? 'foo))
【讨论】:
以上是关于如何在 scm 方案中定义一个函数来测试其参数是不是为宏?的主要内容,如果未能解决你的问题,请参考以下文章