In part 1 I made the point that we should introduce threading macros by starting with as->
('thread-as') instead of ->
('thread-first') or ->>
('thread-last'). Well, maybe it would be wise to back up even further and start with let
.
As a reminder, here's the end goal:
(->> (range)
(map #(* % %))
(filter even?)
(take 10)
(reduce +))
But let's start off without using any threading operators. Rather, let's use let
to label each step-by-step transformation of the data:
(let [numbers (range)
squares (map #(* % %) numbers)
evens (filter even? squares)
first10 (take 10 evens)
sum (reduce + first10)]
sum)
Now let's take it one step toward a threading macro by rebinding the result of each step to a repeated symbol ($
):
(let [$ (range)
$ (map #(* % %) $)
$ (filter even? $)
$ (take 10 $)
$ (reduce + $)]
$)
Now I think we can slip in the 'thread-as' macro (the main hurdle here is reversing the order of $ (range)
):
(as-> (range) $
(map #(* % %) $)
(filter even? $)
(take 10 $)
(reduce + $))
And now the 'thread-last' macro is quite accessible:
(->> (range)
(map #(* % %))
(filter even?)
(take 10)
(reduce +))
So, let
, then as->
, then ->>
.