Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013

1,145 views

Published on

Slides used for the exercises in the Macros hands-on at LambdaJam 2013 in Brisbane, Australia and CUFP 2013 in Boston, USA.

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,145
On SlideShare
0
From Embeds
0
Number of Embeds
9
Actions
Shares
0
Downloads
19
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013

  1. 1. Bending Clojure to your Will: Macros and Domain Specific Languages CUFP - Boston, 2013 Leonardo Borges @leonardo_borges www.leonardoborges.com www.thoughtworks.com Thursday, 19 September 13
  2. 2. Leonardo Borges @leonardo_borges www.leonardoborges.com www.thoughtworks.com • Thoughtworker • Functional Programming enthusiast • Clojure Evangelist • Founder & Organiser of the Sydney Clojure User Group (clj-syd) • World traveller • Fan of Murray’s Beers :) about:me Thursday, 19 September 13
  3. 3. Why macros? Thursday, 19 September 13
  4. 4. It’s fun Thursday, 19 September 13
  5. 5. Thursday, 19 September 13
  6. 6. It’s powerful Thursday, 19 September 13
  7. 7. Thursday, 19 September 13
  8. 8. It’s mind bending Thursday, 19 September 13
  9. 9. Thursday, 19 September 13
  10. 10. If you give someone Fortran, he has Fortran. If you give someone Lisp, he has any language he pleases. - Guy Steele Thursday, 19 September 13
  11. 11. But what are macros? Thursday, 19 September 13
  12. 12. •Data is code is data •Programs that write programs •Magic happens at macro-expansion time •Most control structures in Clojure are built out of macros But what are macros? Thursday, 19 September 13
  13. 13. Macro-expansion time (defmacro arg-logger [& args] (prn "Called with: " args) `(do ~@args)) Thursday, 19 September 13
  14. 14. Macro-expansion time (arg-logger (+ 2 3)) Every usage of a macro (do (+ 2 3)) Gets replaced with its expansion prior to compilation Thursday, 19 September 13
  15. 15. Runtime (arg-logger (+ 2 3)) ;;"Called with: " ((+ 2 3)) Arguments are handed into macros unevaluated Thursday, 19 September 13
  16. 16. More on that later Thursday, 19 September 13
  17. 17. Debugging macros (macroexpand '(cond true "true" :else "false")) ;;(if true "true" (clojure.core/cond :else "false")) Thursday, 19 September 13
  18. 18. Debugging macros (require '[clojure.walk :as w]) (w/macroexpand-all '(cond true "true" :else "false")) ;;(if true "true" (if :else "false" nil)) Thursday, 19 September 13
  19. 19. Quoting Prevents evaluation (def my-list (1 2 3)) ;java.lang.Integer cannot be cast to clojure.lang.IFn (def my-list '(1 2 3)) ;Success! 'my-list ;my-list '(1 2 3) ;(1 2 3) Thursday, 19 September 13
  20. 20. Syntax-quote Automatically qualifies all unqualified symbols `my-list ; user/my-list `prn ; clojure.core/prn Note the backtick! Thursday, 19 September 13
  21. 21. Unquote Evaluates some forms in a quoted expression Before unquoting... `(map even? my-list) ;;(clojure.core/map clojure.core/even? user/my-list) After... `(map even? '~my-list) ;;(clojure.core/map clojure.core/even? (quote (1 2 3))) Thursday, 19 September 13
  22. 22. Unquote-splicing “Unpacks” a sequence Before unquote-splicing... `(+ ~my-list) ;;(clojure.core/+ (1 2 3)) (eval `(+ ~my-list)) ;;java.lang.Integer cannot be cast to clojure.lang.IFn Thursday, 19 September 13
  23. 23. Unquote-splicing After... `(+ ~@my-list) ;;(clojure.core/+ 1 2 3) (eval `(+ ~@my-list)) ;;6 Thursday, 19 September 13
  24. 24. All of these are useful inside macros! Thursday, 19 September 13
  25. 25. Jam time! Thursday, 19 September 13
  26. 26. Jam time! •Get the code - http://bit.ly/cufp-2013-macros •Make sure you have leiningen 2.x installed •Run $lein midje or lein midje :autotest from the project root •Watch the tests fail! •Fix them :) Thursday, 19 September 13
  27. 27. Summary (defmacro macro-name [& args] ...)Defining macros (def my-list '(1 2 3))Quoting `(+ my-list) ; (clojure.core/+ user/my-list)Syntax-quote `(+ ~my-list) ; (clojure.core/+ (1 2 3))Unquote (macroexpand '...) (require '[clojure.walk :as w]) (w/macroexpand-all '...) Debugging Unquote-splicing `(+ ~@my-list) ; (clojure.core/+ 1 2 3) Thursday, 19 September 13
  28. 28. Questions? Leonardo Borges @leonardo_borges www.leonardoborges.com www.thoughtworks.com Thursday, 19 September 13
  29. 29. Go deeper Let Over Lambda - http://bit.ly/let-over-lambda On Lisp - http://bit.ly/on-lisp-book Thursday, 19 September 13

×