{"id":15164,"date":"2013-07-05T22:00:01","date_gmt":"2013-07-05T19:00:01","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=15164"},"modified":"2013-07-05T11:16:22","modified_gmt":"2013-07-05T08:16:22","slug":"macro-lifecycle-in-clojure","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html","title":{"rendered":"Macro lifecycle in Clojure"},"content":{"rendered":"<p>If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn when macros are recognized, evaluated, expanded and executed. I believe the most important concept is their similarity to normal functions. As I described <a href=\"http:\/\/www.javacodegeeks.com\/2013\/06\/clojure-macros-for-beginners.html\">last time<\/a>, macros are ordinary functions but executed at compile time and taking code rather than values as arguments. The second difference is slightly artificial since Clojure code <i>is<\/i> a value in sense that it can be passed around. So let us focus on when macros are actually expanded and executed. We will start from trivial <a href=\"http:\/\/rosettacode.org\/wiki\/Greatest_common_divisor#Clojure\">GCD implementation in Clojure<\/a> as a normal function:<br \/>\n&nbsp;<br \/>\n&nbsp;<\/p>\n<pre class=\"brush:java\">(defn gcd [a b]\r\n    (if (zero? b)\r\n        a\r\n        (recur b (mod a b))))<\/pre>\n<p>Calling this function will result in a tail-recursive loop executed<br \/>\n<b>at runtime<\/b> every time it is encountered:<\/p>\n<pre class=\"brush:java\">user=&gt; (gcd 18 12)\r\n6\r\nuser=&gt; (gcd 9 2)\r\n1\r\nuser=&gt; (gcd 9 (inc 2))\r\n3<\/pre>\n<p>Not very exciting. But what if we wrap reference to <code>gcd<\/code> inside a macro?<\/p>\n<pre class=\"brush:java\">\t\r\n(defmacro runtime-gcd [a b] (list 'gcd a b))<\/pre>\n<p>Or more concise syntax:<\/p>\n<pre class=\"brush:java\">(defmacro runtime-gcd-quote [a b] `(gcd ~a ~b))<\/pre>\n<p>Now look at the declaration of <code>runtime-gcd<\/code> but replace <code>defmacro<\/code> with <code>defn<\/code>, just as if it was a normal function:<\/p>\n<pre class=\"brush:java\">(defn runtime-gcd-fun [a b] (list 'gcd a b))<\/pre>\n<p>Every time you call <code>runtime-gcd-fun<\/code> in your Clojure code, it gets replaced with the following list: <code>(gcd 12 8)<\/code>. As you can see it is basically a <code>gcd<\/code> function call. It is quoted, thus remains a list rather than invoking the actual function. You can evaluate this data structure by running <code>(eval)<\/code>:<\/p>\n<pre class=\"brush:java\">user=&gt; (eval '(gcd 12 8))\r\n4\r\nuser=&gt; (eval (list 'gcd 12 8))\r\n4\r\nuser=&gt; (eval (runtime-gcd-fun 12 8))\r\n4<\/pre>\n<p>As you can see <code>runtime-gcd-fun<\/code> is a function that produces data structure (<code>list<\/code>) that happens to be valid Clojure <i>code<\/i>! <code>runtime-gcd-fun<\/code> does not call <code>(gcd a b)<\/code>, it returns code (expression) that invokes <code>gcd<\/code>. OK, but what does it have to do with macros? Let\u2019s go back to our original <code>runtime-gcd<\/code> macro:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java\">user=&gt;     (defmacro runtime-gcd [a b] (list 'gcd a b))\r\n#'user\/runtime-gcd\r\nuser=&gt; (runtime-gcd 12 8)\r\n4\r\nuser=&gt; (runtime-gcd 12 (inc 7))\r\n4<\/pre>\n<p>Sooo\u2026 where is the difference? Nowhere, yet. <code>(defmacro)<\/code> is executed (<i>expanded<\/i>) at compile time. It is basically a function invoked during compilation. Just like an invocation of normal function is replaced with its value at runtime, value returned from a macro replaces every occurrence of that macro in code. Before it even gets compiled down to bytecode. So if <code>runtime-gcd<\/code> is encountered, compiler calls it and replaces it with its result, that is: <code>(gcd a b)<\/code>. This means we can simply replace e.g. <code>(runtime-gcd 12 8)<\/code> with <code>(gcd 12 8)<\/code> &#8211; this is what the compiler is doing for us anyway.<\/p>\n<p>What\u2019s the big deal, then? So far macros are just fancy functions executed during compilation. But what if we skip quoting and define<br \/>\n<code>compile-time-gcd<\/code> as follows?<\/p>\n<pre class=\"brush:java\">user=&gt; (defmacro compile-time-gcd [a b] (gcd a b))\r\n#'user\/compile-time-gcd\r\nuser=&gt; (compile-time-gcd 12 8)\r\n4<\/pre>\n<p>Stay we me, you are <i>this<\/i> close to enlightenment. Notice that we no longer quote <code>gcd<\/code> invocation. This has tremendous consequences. This time when compiler encounters <code>compile-time-gcd<\/code> macro it executes its body (<i>expands it<\/i>). While body of <code>runtime-gcd<\/code> was calling <code>list<\/code> function (thus returning a list), body of <code>compile time-gcd<\/code> calls <code>gcd<\/code> immediately &#8211; and remember this happens at compile time! <code>(gcd 12 8)<\/code> is executed by the compiler and its value (<code>4<\/code>) is returned as macro expansion result. This means that the whole <code>(compile-time-gcd 12 8)<\/code> is replaced <b>at compile time<\/b> with number <code>4<\/code>. In other words the computation was done during compilation and <code>gcd<\/code> overhead is non-existent at runtime. Check out the output of <code>macroexpand<\/code> that shows what macro returns without evaluating it:<\/p>\n<pre class=\"brush:java\">user=&gt; (macroexpand '(runtime-gcd 12 8))\r\n(gcd 12 8)\r\n \r\nuser=&gt; (macroexpand '(compile-time-gcd 12 8))\r\n4<\/pre>\n<p>This is something you should really think about. Macros are not just advanced search-and-replace facilities built into the compiler. They are \u201creal\u201d Clojure functions that can have logic and conditions. The only difference is that they work at compile time and operate on code rather than on values. So why not use macros all the time if they can run the program at compile time and avoid runtime computations? Remember that macros live in the compiler only, they don\u2019t know anything about your runtime environment:<\/p>\n<pre class=\"brush:java\">user=&gt; (compile-time-gcd 12 (inc 7))\r\nClassCastException clojure.lang.PersistentList cannot be cast to java.lang.Number \r\n    clojure.lang.Numbers.isZero (Numbers.java:90)<\/pre>\n<p>This error will actually pop-up during compilation, not at runtime! The compiler tries to run <code>(gcd 12 '(inc 7))<\/code>. Quoted <code>'(inc 7)<\/code> list is not equal to number 8. It\u2019s a <code>list<\/code>! And when the compiler executes the condition <code>(zero? '(inc 7))<\/code> familiar <code>ClassCastException<\/code> is thrown. Don\u2019t confuse it with seemingly similar <code>(zero? (inc 7))<\/code> &#8211; incrementing <code>7<\/code> is not quoted and thus evaluates to <code>8<\/code>.<\/p>\n<p>Are you still confused? Let\u2019s make it even more explicit:<\/p>\n<pre class=\"brush:java\">(defmacro printer [s]\r\n    (println \"Compile time:\" s)\r\n    (list 'println \"Runtime:\" s))<\/pre>\n<p>This macro is a function with two expressions. Now compile the following Clojure file:<\/p>\n<pre class=\"brush:java\">(printer \"buzz\")\r\n(printer (str \"foo\" \"bar\"))<\/pre>\n<p>Look carefully at the <b>compiler<\/b> output, you will see the following two lines:<\/p>\n<pre class=\"brush:java\">Compile time: buzz\r\nCompile time: (str foo bar)<\/pre>\n<p>This proves that macros are expanded and executed at compile time. But what happened with the second line? Well, value of last expression of any function (macros are not exception here) becomes value of that function. Thus every occurrence of <code>(printer s)<\/code> macro is replaced with <code>(println \"Runtime:\" s)<\/code> <i>list<\/i> &#8211; and this piece of code will be compiled just as if was <code>println<\/code> from the very beginning.<\/p>\n<p>In order to make sure you understand macros really well, switch statements in <code>printer<\/code> macro and try to figure out what will this macro do, both at compile- and run-time (hint: value of <code>println<\/code> is <code>nil<\/code>):<\/p>\n<pre class=\"brush:java\">(defmacro broken-printer [s]\r\n    (list 'println \"Runtime:\" s)\r\n    (println \"Compile time:\" s))<\/pre>\n<p>We are not even close to explaining all aspects of macros in Clojure. We have not covered various quoting quirks, <code>gensym<\/code>, splicing, etc. But I hope this article (together with <a href=\"http:\/\/nurkiewicz.blogspot.no\/2013\/06\/clojure-macros-for-beginners.html\">Clojure macros for beginners<\/a>) will give you some basic idea why macros are so essential in Lisp family of languages.<br \/>\n&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/nurkiewicz.blogspot.com\/2013\/07\/macro-lifecycle-in-clojure.html\">Macro lifecycle in Clojure<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Tomasz Nurkiewicz at the <a href=\"http:\/\/nurkiewicz.blogspot.com\/\">Java and neighbourhood<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn when macros are recognized, evaluated, expanded and executed. I believe the most important concept is their similarity to normal functions. As I described last time, macros are &hellip;<\/p>\n","protected":false},"author":13,"featured_media":93,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-15164","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-clojure"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Macro lifecycle in Clojure<\/title>\n<meta name=\"description\" content=\"If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Macro lifecycle in Clojure\" \/>\n<meta property=\"og:description\" content=\"If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2013-07-05T19:00:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tomasz Nurkiewicz\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/tnurkiewicz\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tomasz Nurkiewicz\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html\"},\"author\":{\"name\":\"Tomasz Nurkiewicz\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fb1be85725c10e8361e641fa851e79e1\"},\"headline\":\"Macro lifecycle in Clojure\",\"datePublished\":\"2013-07-05T19:00:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html\"},\"wordCount\":825,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"articleSection\":[\"Clojure\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html\",\"name\":\"Macro lifecycle in Clojure\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"datePublished\":\"2013-07-05T19:00:01+00:00\",\"description\":\"If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/clojure-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/macro-lifecycle-in-clojure.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JVM Languages\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/jvm-languages\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Clojure\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/jvm-languages\\\/clojure\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Macro lifecycle in Clojure\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fb1be85725c10e8361e641fa851e79e1\",\"name\":\"Tomasz Nurkiewicz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g\",\"caption\":\"Tomasz Nurkiewicz\"},\"description\":\"Java EE developer, Scala enthusiast. Enjoying data analysis and visualization. Strongly believes in the power of testing and automation.\",\"sameAs\":[\"http:\\\/\\\/nurkiewicz.blogspot.com\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/tnurkiewicz\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/tomasz-nurkiewicz\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Macro lifecycle in Clojure","description":"If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html","og_locale":"en_US","og_type":"article","og_title":"Macro lifecycle in Clojure","og_description":"If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn","og_url":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2013-07-05T19:00:01+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","type":"image\/jpeg"}],"author":"Tomasz Nurkiewicz","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/tnurkiewicz","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Tomasz Nurkiewicz","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html"},"author":{"name":"Tomasz Nurkiewicz","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fb1be85725c10e8361e641fa851e79e1"},"headline":"Macro lifecycle in Clojure","datePublished":"2013-07-05T19:00:01+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html"},"wordCount":825,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","articleSection":["Clojure"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html","url":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html","name":"Macro lifecycle in Clojure","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","datePublished":"2013-07-05T19:00:01+00:00","description":"If you still struggle to understand what are macros in Clojure and why are they so useful, I will guide you through another example today. We will learn","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/clojure-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/macro-lifecycle-in-clojure.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JVM Languages","item":"https:\/\/www.javacodegeeks.com\/category\/jvm-languages"},{"@type":"ListItem","position":3,"name":"Clojure","item":"https:\/\/www.javacodegeeks.com\/category\/jvm-languages\/clojure"},{"@type":"ListItem","position":4,"name":"Macro lifecycle in Clojure"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fb1be85725c10e8361e641fa851e79e1","name":"Tomasz Nurkiewicz","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g","caption":"Tomasz Nurkiewicz"},"description":"Java EE developer, Scala enthusiast. Enjoying data analysis and visualization. Strongly believes in the power of testing and automation.","sameAs":["http:\/\/nurkiewicz.blogspot.com\/","https:\/\/x.com\/https:\/\/twitter.com\/tnurkiewicz"],"url":"https:\/\/www.javacodegeeks.com\/author\/tomasz-nurkiewicz"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/15164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=15164"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/15164\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/93"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=15164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=15164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=15164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}