Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Yet Compelling Macro Examples which are Not Already in Clojure

Tags:

macros

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

http://learnclojure.blogspot.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html

like image 307
John Lawrence Aspden Avatar asked Sep 14 '10 16:09

John Lawrence Aspden


2 Answers

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

like image 197
Arthur Ulfeldt Avatar answered Nov 20 '22 06:11

Arthur Ulfeldt


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
like image 4
kotarak Avatar answered Nov 20 '22 05:11

kotarak