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.