CLisp: Thread last - like Clojure
Thread last - Common Lisp implementation
These days I’ve been playing with Clojure
and one macro I really liked was
->>
which is called Thread last
.
What does it do
Thread last is very cool. In essence it takes the result of your one function call and threads it in front of another one. Let me show you what I mean
(->> 1
(+ 2 )
(+ 3 )
(+ 4 )) ; -> 10
And the more explicit version of it
(->> 1 ; let's call it X to see it
(+ 2 ) ; this gets transformed to (+ 2 X), let's call the result of this Y
(+ 3 ) ; this gets transformed to (+ 3 Y), let's call the result of this Z
(+ 4 )) ; this gets transformed to (+ 3 Z) whic is then equal to 10
Pretty cool , because otherwise the operation would have been written as :
(+ 4 (+ 3 (+ 2 1)))
In this case it is not the worst - but the longer the calls the more complex the calls the more you would need to read from inside out.
CLisp doesn’t have this
Or at least yet CLisp doesn’t, I read somewhere that Clisp 21 does. But, let us have a go at implementing it
(defmacro ->> (var &rest lst)
(if (car lst) ; if the lists of remaining operations is not empty
`(->> (,@(car lst) ,var) ,@(cdr lst)) ; recursively call the macro
`,var)) ; otherwise, return the var.
So what the above macro is recursively create the call. Let’s run through the above example step by step to see the macroexpansion
Step by step Macroexpansion
Step 0 - The call itself
(->> 1
(+ 2)
(+ 3)
(+ 4))
or inline it would be
(->> 1 (+ 2) (+ 3) (+ 4))
Step 1 - The first macro-expansion
(->> (+ 2 1) (+ 3) (+ 4))
So we see, the macro takes the first element of the list and the first element of the arguments and places the it at the end of this call. Then it recursively calls itself again.
Step 2 - The first macro-expansion (again)
(->> (+ 3 (+ 2 1)) (+ 4))
It treates (+ 2 1) as it treated 1 and it appends it to the car
of the opperation list
Step 3 - You guessed it, the first macro-expansion (again)
But this time it is the second branch of the if
(+ 4 (+ 3 (+ 2 1)))
Step 4 - Rejoice
… and marvel, at how easy it was to implement the feature of clojure
in
common lisp
using a simple recursive macro
.