Simple Yet Compelling Macro Examples which are Not Already in Clojure
I'm trying to write a macro tutorial, and now I need some examples which are simple to understand, and yet compelling.
The problem is that a lot of the obvious things are already in clojure and contrib. And I feel that "look, we can reimplement all the library functions" might not be the best argument for why macros are so great.
Has anyone got any cute (one-liners are best) examples that they wouldn't mind me using?
Here are the first three parts of the tutorial. It's a bit ropy at the moment, so any comments about how it could be made better would be gratefully received.
http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-i-getting.html
http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html
开发者_StackOverflow社区http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html
I'm working on some cryptography software in clojure. Its really fun and using unit testing makes it more fun because I don't get nervous about breaking things. The trouble is that all the crypto functions generate different results every time because they are driven by a fairly good IMHO psudo random number generator.
How do I test randomized functions?
with a bind macro of course!
(defmacro with-fake-prng [ & exprs ]
"replaces the prng with one that produces consisten results"
`(binding [com.cryptovide.split/get-prng (fn [] (cycle [1 2 3]))
com.cryptovide.modmath/mody 719
com.cryptovide.modmath/field-size 10]
~@exprs))
then I wrap my test functions in (with-fake-prng (deftest mytest ....))
clojure has a lot of these "bind macroes". like with-out-string
and such.
I also have a macro that loads every namespace into the repl. (I dont use this much now that I have switched to cake)
(defmacro load-all []
'(use
:reload-all
'com.cryptovide.modmath
...
'com.cryptovide.gui
'com.cryptovide.checksum
'com.cryptovide.log))
ps: always mind the first rule of macro club
I would talk more about patterns: when and how is a macro used. eg...
- Protecting a resource. Examples:
binding
,with-open
, ...(let [~x (get-resource)] (try ~@dostuff (finally (release-resource ~x))))
- Defining things. Examples:
defn
,defsnippet
(enlive),defservice
(ring) - Macro/driver split. Especially this technique takes away a lot of macro pain.
Like multiple evaluation or capture. Example:
with-bindings
- Beautifying ugly code. eg. when Taming multi-dim arrays
精彩评论