I would like to have a macro which I'll call def-foo. Def-foo will create a function, and then will add this function to a set.
So I could call
(def-foo bar ...)
(def-foo baz ...)
And then there would be some set, e.g. all-foos, which I could call:
all-foos
=> #{bar, baz}
Essentially, I'm just trying to avoid repeating myself. I could of course define the functions in the normal way, (defn bar ...) and then write the set manually.
A better alternative, and simpler than the macro idea, would be to do:
(def foos #{(defn bar ...) (defn baz ...)} )
But I'm still curious as to whether there is a good way for the macro idea to work.
Do you want to end up with a set that has the names of functions in it (i.e. a set of Symbols), or a set containing vars (which resolve to functions)? If you want the former, you can add the symbols to an atom in the macro at compile-time, like Greg Harman's version.
If you want the latter, your macro must expand to code that does the atom-swapping after the function is defined. Remember that macros run at compile-time and the macro-expanded result runs at run-time; the function itself is not available until run-time.
(def all-foos (atom #{}))
(defmacro def-foo [x]
`(let [var# (defn ~x [] (println "I am" '~x))]
(swap! all-foos conj var#)))
If you want to be able to call the functions in this set, for example, you need to use the latter version.
user> (def-foo foo)
#{#'user/foo}
user> (def-foo bar)
#{#'user/foo #'user/bar}
user> ((first @all-foos))
I am foo
nil
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With