Explain Clojure’s “for”, line by line

Or, how to read cryptic documentation and make sense of it

Yizhe Sun
Yizhe Sun
Apr 15, 2020 · 3 min read
Lines of text from a book
Lines of text from a book
Photo by J-S Romeo on Unsplash

Recently I came across a rant on Reddit about clojure’s unfriendly documentation. One example mentioned is the documentation of for. The official doc reads as follows:

List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: :let [binding-form expr …], :while test, :when test.

(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))

It looks intimidating.But fear not! If you’re new to clojure and looking to learn how to use for in clojure, here’s a line-by-line explanation of what the official doc means.

1. List comprehension.

Clojure’s for does list comprehension, which is slightly different from thosefor loops that you may know from Java or Javascript. A list comprehension constructs a list(or seq in clojure’s case) by evaluating the body, then collecting the result of each iteration. For example, (for [x (range 5)] (+ x 2)) gives you (2 3 4 5 6). (Recall that range generates a sequence of integers).

2. Takes a vector of one or more binding-form/collection-expr pairs…

“Binding-form” means “loop variable”(although in clojure, variables are by default immutable). “Collection-expr” is the collection you want to loop through. Any seq can be iterated, such as vectors, lists, and maps(as a sequence of key-value pairs). You can learn more about seq here.

3. …each followed by zero or more modifiers…

Sometimes you may want to terminate the loop early, or skip certain values. We’ll come back to “modifiers” near the end of this article.

4. …and yields a lazy sequence of evaluations of expr.

Sequences constructed with for are lazy, which means that the actual computation is delayed until you need to look at the value of it(e.g. you want to print it to the REPL). In addition to being more efficient, laziness makes it possible to work with *infinite sequence*, i.e. sequences that have an infinite number of values in it, by limiting calculation to what you really need. Sounds like magic, right?

5. Collections are iterated in a nested fashion…

That is, you can use multiple loop variables similar to a nested for loop in other languages. For example, (for [x [1 2 3] y [2 3 4]] (* x y)) gives you [2 3 4 4 6 8 6 9 12] .

6. …rightmost fastest…

“Fastest” means “the most inner loop”. Note that we often add extra newlines between loop variables to improve readability, so “rightmost” can sometimes means “bottom-most”, like this:

7. …and nested coll-exprs can refer to bindings created in prior binding-forms.

This is best illustrated with an example.

8. Supported modifiers are: :let [binding-form expr …], :while test, :when test.

This is the part where the doc fails us. What are these modifiers? What are they good for? After some experimenting with the REPL, here’s a summary:

  • :let works as a local binding, similar to clojure’s let .

These modifiers are illustrated in the following example:

Finally, the doc provides one example of usage. Try understand what it does, and use the REPL to check the answer. You can find more examples here.

And that’s it for the doc! If you’ve made it to the end, you are doing great! Clojure’s for is concise and expressive. I hope you have a good time using it!

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store