Reputation: 145
I am trying to write a macro that generates patterns for the core.match macro.
(defmacro match2
[state i predecessor]
`(match ~[state]
[(~(vec (concat (repeat i '_)
predecessor
'(& r)))
:seq)] ~i
:else false))
And this works fine if I use it directly with hardcoded predecessor:
(match2 ["B"] 0 ["B"]) ; 0
So far everything is fine, but if I try to pass the predecessor using function call:
(match2 ["B"] 0 ((fn [] ["B"]))) ; AssertionError Invalid list syntax [] in (fn [] ["B"])
The problem is that because match2 is a macro clojure won't evaluate the function call, and will just pass the form as it is. The unevaluated form then goes to core.match (again unevaluated, because core.match is itself a macro) and core.match throws exception because the form is not correct pattern.
How can I force evaluation on macro argument? Or any other workaround?
I was hinted that this is usually done with a second macro, but my attempts yielded no good results.
Upvotes: 2
Views: 823
Reputation: 24771
I see two options. Use eval in your macro.
Or, you could have your macro not call the match macro. Have it call another function which calls the match macro. That will force evaluation en route to match.
Here is a good article to read about this type of problem:
http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros
Upvotes: 3
Reputation: 301
core.match
is a compiler. It turns some forms into executable expressions. The forms it can process must respect a syntax, hence the assert throw. As a macro, it compiles at... compile time. However hard you try, you cannot have it compile the result of runtime expressions.
Even if you manage to get (fn [] ["B"])
evaluated at compile time so to feed the value to match
, this is not your goal I presume. What you're trying to do is to feed match with expressions evaluated by your program's logic. Been there, sorry to say it is not possible with core.match
, which D. Nolen confirmed.
Nevertheless, matchure
can do just that: create match functions / expressions at runtime, see fn-match
. It is unmaintained AFAIK but just works. I've patched it some time ago to use clj 1.6, here.
Upvotes: -1