2

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

> (macro? 'match)
#t
> (macro? 'car)
#f
msantos
  • 21
  • 1

2 Answers2

1

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

> (procedure? car)
#t
Sven
  • 496
  • 4
  • 9
  • 1
    Does this really work for macros? Isn't `(procedure? let)` a syntax error? – Florian Weimer Nov 16 '20 at 21:56
  • @FlorianWeimer Yes, you might need to catch an error. In bigloo, your example reports `Unbound variable -- let`. – Sven Nov 17 '20 at 08:43
  • Thank you both for your help with this. Perhaps this is a good time to provide you with my rationale for asking that question: a couple of months ago, while I was trying to port Andrew Wright's Softscheme system to a modern Scheme (Bigloo, ChezScheme, or Racket), I came across that 'macro?' function call in his source code (written in ChezScheme from the early 90's). Apparently, that function was in those early (proprietary) versions of chezscheme. – msantos Nov 18 '20 at 01:44
1

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))
Florian Weimer
  • 32,022
  • 3
  • 48
  • 92