Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active May 29, 2019 20:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Integralist/11394651 to your computer and use it in GitHub Desktop.
Save Integralist/11394651 to your computer and use it in GitHub Desktop.
Clojure's "Thread First" and "Thread Last" macros

In Clojure macros are executed before code is evaluated. Macros allow us to manipulate the program being compiled. There are two macros in particular that I like to demonstrate why this is useful:

  • Thread First ->
  • Thread Last ->>

Note: in Clojure sequence data structures (lists & vectors) are usually the last item in an argument list; where as map data structures are usually the first argument in an argument list

Thread First

Our original program requires us to effectively read it "inside out":

(dissoc
  (assoc 
    {:name "Jonathan" :password "secret"} 
    :nickname "Jon") 
  :password)

; => {:nickname "Jon", :name "Jonathan"}

But as humans we prefer to read things the other way around (this is where Thread First can help):

(-> {:name "Jonathan" :password "secret"}
    (assoc :nickname "Jon")
    (dissoc :password))

; => {:nickname "Jon", :name "Jonathan"} 

As you can see, we're telling it to pass the map data structure as the first argument to each of the subsequent lists to be processed. This allows us to read the code in a more natural flow. But as macros are run before code is evaluated, Clojure will receive it in its original form and evaluate that original code.

Thread Last

This macro works the same way but for sequences (see the Note above).

(reduce + (filter odd? (map inc (range 10))))

; you can write it long form if you prefer:
(reduce + 
  (filter odd? 
    (map inc 
      (range 10))))

; => 25

And now rewritten in a more natural flow...

(->> (range 10) (map inc) (filter odd?) (reduce +))

; you can write it long form if you prefer:
(->> (range 10)
     (map inc)
     (filter odd?)
     (reduce +))

; => 25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment