例如,假设"match"是宏,而"car"不是:
> (macro? 'match)
#t
> (macro? 'car)
#f
大多数方案都没有这样的macro?
函数。要区分正常函数和宏,可以使用RnRS:中的procedure?
> (procedure? car)
#t
问题是无法使用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))