如何在 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 方案中定义一个函数来测试其参数是不是为宏?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查是不是设置了可选功能参数

检查单元测试中是不是抛出参数

如何实现JS函数的重载

在 C 中是不是有一个函数可以用作“实例方法”?

如何检查R的参数(...)中是不是定义了任何变量?

相关支付业务测试中如何保证幂等性