# Favorite macros

**URL:** https://clojureverse.org/t/favorite-macros/2716
**Category:** General Questions
**Created:** [August 25, 2018, 4:59pm UTC](https://clojureverse.org/t/favorite-macros/2716 "2018-08-25T16:59:14Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![pbaille](https://clojureverse.org/user_avatar/clojureverse.org/pbaille/32/1002_2.png) [@pbaille](https://clojureverse.org/u/pbaille)
#### Post date: [August 25, 2018, 4:59pm UTC](https://clojureverse.org/t/favorite-macros/2716/1 "2018-08-25T16:59:14Z")

</div>

I’m trying to learn more about macros, and would like to know about the most beautiful macros you’ve came across along your Lisp journey.

---

<div class="post-metadata">

### Author: ![didibus](https://clojureverse.org/user_avatar/clojureverse.org/didibus/32/951_2.png) [@didibus](https://clojureverse.org/u/didibus)
#### Post date: [August 25, 2018, 8:02pm UTC](https://clojureverse.org/t/favorite-macros/2716/2 "2018-08-25T20:02:41Z")

</div>

I’m a fan of the threading macros `->` `->>` `some->` `as->` , etc. Once you get a hang of them, you want to use them everywhere. I think they solve one of the downsides of the Lisp syntax, by allowing to order things in the more familiar left to right order, instead of the inside out order of Lisp.

I’m a big fan of `doto`. It almost makes it nicer to interop with Java libs from Clojure, then from Java itself.

I also enjoy `if` `case` `cond` `condp`, `when` `when-let` `if-let`. Together they provide a very complete set of conditional flow controls.

`loop` and `recur` I find is a very ingenious use, to allow tail recursion at the syntax level.

I like `for` and `doseq`, and I actually wished Clojure had more list comprehension macros.

Finally, a shout out to core.async `go` `thread` and `alt` macros. It’s a really good example of their inherent power.

---

<div class="post-metadata">

### Author: ![green-coder](https://clojureverse.org/user_avatar/clojureverse.org/green-coder/32/1752_2.png) [@green-coder](https://clojureverse.org/u/green-coder)
#### Post date: [August 28, 2018, 10:16am UTC](https://clojureverse.org/t/favorite-macros/2716/3 "2018-08-28T10:16:27Z")

</div>

The most “efficient” macro that I am aware of, considering its usefulness compared to its size:

> <https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L4677>

---

<div class="post-metadata">

### Author: ![pbaille](https://clojureverse.org/user_avatar/clojureverse.org/pbaille/32/1002_2.png) [@pbaille](https://clojureverse.org/u/pbaille)
#### Post date: [August 28, 2018, 4:35pm UTC](https://clojureverse.org/t/favorite-macros/2716/4 "2018-08-28T16:35:00Z")

</div>

i’ve posted two related questions on quora that had interesting answers:  
[https://www.quora.com/What-are-some-good-examples-of-macro-generating-macros-in-Lisp](https://www.quora.com/What-are-some-good-examples-of-macro-generating-macros-in-Lisp)  
[https://www.quora.com/What-are-the-most-beautiful-LISP-macros-that-you-know](https://www.quora.com/What-are-the-most-beautiful-LISP-macros-that-you-know)

---

<div class="post-metadata">

### Author: ![tgetgood](https://clojureverse.org/user_avatar/clojureverse.org/tgetgood/32/1480_2.png) [@tgetgood](https://clojureverse.org/u/tgetgood)
#### Post date: [September 10, 2018, 2:57pm UTC](https://clojureverse.org/t/favorite-macros/2716/5 "2018-09-10T14:57:35Z")

</div>

In my experience, really powerful macros generally aren’t beautiful ([case in point](https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L403)), but their effects are.

Macros let you build up your language to fit your problem domain at the same time that the rest of your code fits your problem domain to your language. The result, if done with skill, is a tight, clean fit. A simple and easy to understand program with the bodies carefully buried in the backyard.

This is important, so I’ll say it again: macros don’t make your code simpler. They sequester complexity. This can make the system more reliable, because there is less surface area for error, but if you’re not careful that small patch can be a nightmare.

If you want to see macros do things you didn’t think were possible, I would recommend reading [On Lisp](http://www.paulgraham.com/onlisptext.html) and [Let Over Lambda](https://letoverlambda.com/) (ideally in that order). They’re both in Common Lisp, but the ideas translate very easily into Clojure.

---

<div class="post-metadata">

### Author: ![DjebbZ](https://clojureverse.org/user_avatar/clojureverse.org/djebbz/32/531_2.png) [@DjebbZ](https://clojureverse.org/u/DjebbZ)
#### Post date: [September 12, 2018, 3:36pm UTC](https://clojureverse.org/t/favorite-macros/2716/6 "2018-09-12T15:36:04Z")

</div>

Another book specifically on Clojure Macros is [Mastering Clojure Macros](https://pragprog.com/book/cjclojure/mastering-clojure-macros), that shows almost all use-cases of macros. I enjoyed the read.

---

<div class="post-metadata">

### Author: ![hlship](https://clojureverse.org/user_avatar/clojureverse.org/hlship/32/1147_2.png) [@hlship](https://clojureverse.org/u/hlship)
#### Post date: [September 12, 2018, 4:20pm UTC](https://clojureverse.org/t/favorite-macros/2716/7 "2018-09-12T16:20:49Z")

</div>

I add this one to many of my projects:

```auto
(defmacro cond-let
  "A version of `cond` that allows for `:let` terms."
  [& forms]
  {:pre [(even? (count forms))]}
  (when forms
    (let [[test-exp result-exp & more-forms] forms]
      (if (= :let test-exp)
        `(let ~result-exp
           (cond-let ~@more-forms))
        `(if ~test-exp
           ~result-exp
           (cond-let ~@more-forms))))))

```

It’s how I wish `clojure.core/cond` worked, allowing a `:let` in the middle (much like `for`).

---

<div class="post-metadata">

### Author: ![DjebbZ](https://clojureverse.org/user_avatar/clojureverse.org/djebbz/32/531_2.png) [@DjebbZ](https://clojureverse.org/u/DjebbZ)
#### Post date: [September 12, 2018, 4:30pm UTC](https://clojureverse.org/t/favorite-macros/2716/8 "2018-09-12T16:30:30Z")

</div>

Can you show an example of usage ?

---

<div class="post-metadata">

### Author: ![hlship](https://clojureverse.org/user_avatar/clojureverse.org/hlship/32/1147_2.png) [@hlship](https://clojureverse.org/u/hlship)
#### Post date: [September 12, 2018, 4:58pm UTC](https://clojureverse.org/t/favorite-macros/2716/9 "2018-09-12T16:58:18Z")

</div>

> <https://github.com/walmartlabs/lacinia/blob/e190dd3c8c5d435377808043b52d59eb36fc5a49/src/com/walmartlabs/lacinia.clj#L39>

---

<div class="post-metadata">

### Author: ![hlship](https://clojureverse.org/user_avatar/clojureverse.org/hlship/32/1147_2.png) [@hlship](https://clojureverse.org/u/hlship)
#### Post date: [September 12, 2018, 4:59pm UTC](https://clojureverse.org/t/favorite-macros/2716/10 "2018-09-12T16:59:06Z")

</div>

It exists to prevent the code from marching towards the right margin.

---

<div class="post-metadata">

### Author: ![DjebbZ](https://clojureverse.org/user_avatar/clojureverse.org/djebbz/32/531_2.png) [@DjebbZ](https://clojureverse.org/u/DjebbZ)
#### Post date: [September 12, 2018, 5:25pm UTC](https://clojureverse.org/t/favorite-macros/2716/11 "2018-09-12T17:25:06Z")

</div>

Just read it. Nice! Indeed it stays flat and very readable. I may have some use for it…

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [March 14, 2019, 5:25am UTC](https://clojureverse.org/t/favorite-macros/2716/12 "2019-03-14T05:25:09Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
