I have a macro defprinter
where I can define functions that: get a value in a dic based on destructuring + print that variable.
This looks like:
(defmacro defprinter [name pattern]
(list 'defn name [pattern] '(prn to-print)))
So I can do something like (defprinter print-lemons {to-print :lemons})
and then (print-lemons {:lemons "lemons"})
and it will print the correct thing (and I can define printers with any kind of destructuring on the first argument).
But now I want to give the option of that function maybe knowing how to print with a color as well, such as, if the symbol color
is defined, it should do (prn color "-colored " to-print)
, but else just (prn color)
.
So, the function generated by (defprinter print-lemons {to-print :lemons})
should work the same as above, while (defprinter print-lemons {to-print :lemons, color :color})
would write a function that performs the colored version.
Moreover, I want the same effect if I do
(let [color "black"] (defprinter print-lemons {to-print :lemons}))
or (def color "black") (defprinter print-lemons {to-print :lemons})
.
Is that possible?
I've tried writing it the following way:
(defmacro defprinter [name pattern]
(list 'defn name [pattern]
'(try (eval '(prn (str color "-colored " to-print)))
(catch java.lang.RuntimeException _
(prn to-print)))))
In my understanding the function the macro will write will try to eval the expression at runtime, fail with a RuntimeException if color
is not defined and then execute the (prn to-print). And even though it would check for the existence of color
at runtime, to-print
(which always need to exist for that function) would be checked at compile time when the macro expands.
But what happens here is that I always get a RuntimeException, even when color
is defined (even if I leave only to-print
on the eval statement, it can't find it but the clause in the catch works fine). Seems like the symbol isn't being resolved as I would expect during eval, but I can't think of any other way to achieve this.
Any suggestions?