【问题标题】: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

【问题讨论】:

    标签: scheme chez-scheme bigloo


    【解决方案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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 2020-05-13
      • 2021-03-19
      相关资源
      最近更新 更多