I have a hopefully easy macro question: how do I accomplish the following, correctly? #lang racket/base
(define-syntax-rule (doit2)
[(eq? 1 2) (printf "two")])
(cond
[(eq? 1 3) (printf "three~%")]
doit2 ; fails "cond: bad syntax (clause is not a test-value pair)"
;[doit2] ; also fails "doit2: use does not match pattern: (doit2)"
[(eq? 1 1) (printf "one~%")])
I’m obviously missing something very basic with the macro processor. I’ve tried this a hundred different ways, including adding parentheses, removing parentheses, define-syntax-parse-rule, and even defmacro (hey, I’m desperate and frustrated, ok?), all to no avail. Help?
Let’s figure out what you have written means.
First, define-syntax-rule
looks like: (define-syntax-rule (id . pattern) template)
So in
(define-syntax-rule (doit2) [(eq? 1 2) (printf "two")])
The identifier id
is doit2
and the pattern is empty.
That means that the template is [(eq? 1 2) (printf "two")]
.
Ah, so your idea is to write (doit2)
in a cond and then get a cond-clause ?
yes.
The issue is that macro applications can’t appear anywhere.
You may find this blog post useful: https://lexi-lambda.github.io/blog/2018/10/06/macroexpand-anywhere-with-local-apply-transformer/
At least the introduction
The syntax of a cond
expression is (cond clause ...)
. and it is up to cond
to determine what a clause is.
A cond-clause always have the form [expr expr ...]
so you can’t put a macro call like (doit2)
instead of a clause.
I can check it out. The problem I’m trying to solve is I have a cond
with say 10 clauses, but 5 of them are very repetitious. I just want to “macro them away”. My mental model (probably incorrect!) is that I can write a macro to scribble on what the compiler sees and compiles. Thanks for the reference.
I think there are two solutions to your problem
First one (which is what I would normally do) is to write your own cond
, say, my-cond
, that knows how to cooperate with the clauses
Second one is to simply use Alexis’s macro at the end of the blog post above.