Clojure Koans 24 Macros Notebook
Original Clojure Koans: https://github.com/functional-koans/clojure-koans/
Clojure Koans Spoilers Alert
Preface: An experienced Clojure developer friend has told me to not use macros for now, loosely paraphrasing them: "Macros are an advanced technique, best to be revisited with more experience, a clear need, and defined use-case."
{:deps {org.clojure/clojure {:mvn/version "1.10.1"} ;; complient is used for autocompletion ;; add your libs here (and restart the runtime to pick up changes) compliment/compliment {:mvn/version "0.3.9"}}}{:hello (clojure-version)}Initial Thoughts
Macros seem foreign and new to me as a first time LISPer. What new powers will they help me unlock as a programmer?
(defmacro hello [x] (str "Hello, " x))(defmacro infix [form] (list (second form) (first form) (nth form 2)));; note: unused-public-var linter warning from clojure-lsp(defmacro infix-concise [form] ((second form) ; Note the syntax-quote (`) and unquote (~) characters! (first form) (nth form 2)));; question 24008: What exactly does the "unquote" (~) character do?;; question 24009: What exactly does the "syntax-qyote" (`) character do?;; question 24010: How advanced exactly are macros, and what learning prerequisites are appropriate/suitable?;; question 24011: What are great use cases for macros?;; question 24012: What are common pitfalls for first time macro writers?(defmacro recursive-infix [form] (cond (not (seq? form)) form (= 1 (count form)) (recursive-infix (first form)) :else (let [operator (second form) first-arg (first form) others (rest (rest form))] (operator (recursive-infix first-arg) (recursive-infix others)))));; "Macros are like functions created at compile time"(= "Hello, Macros!" (hello "Macros!"));; ~~question 24001: What is the significance (and consequences) of macros being created at compile time?~~;; answer 24001a: High level question, too broad, and not immediately helpful at this stage.;; skill 24001: Invoke a macro;; "I can haz infix?"(= 10 (infix (9 + 1)));; description: The `infix` macro is used to take in the arguments `9`, `+`, and `1` to execute the addition operation `nine plus one` to get a result of ten. The text above of "I can haz infix?" is a reference to an Internet meme where the grammatically correct English would be be "Can I have infix?";; question 24002: Is infix notation useful or helpful to Clojure programmers?;; answer 24002a: Perhaps when converting code from other languages or regular text... Though I'd still guess no.;; skill 24002: Invoke a macro that enables non-(Clojure-)standard syntax;; "Remember, these are nothing but code transformations"(= (+ 9 1) (macroexpand (infix (9 + 1))));; question 24003: What exactly is happening here?;; question 24004: Why is `infix` quoted?;; answer 24004a: `infix` is quoted to prevent code execution from;; happening so that way the `macroexpand` can correctly expand `infix`.;; question 24005: What is `macroexpand`?;; answer 24005a: From the docs:;; "Repeatedly calls macroexpand-1 on form until it no longer represents;; a macro form, then returns it. Note neither macroexpand-1 nor;; macroexpand expand macros in subforms.";; question 24006: What is `macroexpand-1`?;; answer 24006a: TBD...;; skill 24003: Expand a macro by using `macroexpand`;; "You can do better than that - hand crafting FTW!"(= (* 10 2) (macroexpand (infix-concise (10 * 2))));; skill 24004: Write your own custom macro;; "Things don't always work as you would like them to... "(= (+ 10 (2 * 3)) (macroexpand (infix-concise (10 + (2 * 3)))));; question 24007: Is this Koan exercise in the wrong order?;; "Really, you don't understand recursion until you understand recursion"(= 36 (recursive-infix (10 + (2 * 3) + (4 * 5))))Closing Thoughts
While excited to try using macros, I am thinking, after speaking with a Clojure friend, that I am best off to indeed "shelve them for now." I wonder how many other Clojure Koans sections, as well as the "well advertised benefits of Clojure" (e.g. as listed on clojure.org) are too advanced/complex for a Clojure/LISP initiate to use correctly/effectively.
;; skill 24005: Rewrite a macro as a functionTo-Do's
[ ] Add research here to helpful macro use-cases
[ ] Consider (brainstorm, research) how might I build my macro thinking skills before I need to use them