How to define a function in scm scheme that tests if its parameter is a macro?

112 views Asked by At

For example, assuming 'match is a macro and 'car isn't:

> (macro? 'match)
#t
> (macro? 'car)
#f
2

There are 2 answers

3
Sven On

Most schemes have no such macro? function. To distinguish normal functions from macros you can use procedure? from RnRS:

> (procedure? car)
#t
0
Florian Weimer On

The problem is that you cannot name the keyword using Scheme syntax:

> (procedure? let)
Exception: invalid syntax let

So you have to use a symbol, like 'let, to refer to it. Given that eval needs to be able to tell keywords apart from other identifiers, you can try something like this:

(define keyword?
    (lambda (symbol)
      (guard (x [else (syntax-violation? x)])
        (eval symbol)
        #f)))
(keyword? 'let) ⇒ #t

(keyword? 'car) ⇒ #f

(keyword? 'does-not-exist) ⇒ #f

But this is certainly a rather big hammer. And this single-argument form of eval is a Chez Scheme extension, supplying (interaction-environment) as the default environment. It is also not completely safe because this hangs:

(let-syntax ([foo (lambda (x) (raise "oops"))])
    (keyword? 'foo))