22 September 2021

'Print-line' Debugging with the 'Thread-as' Macro

Yet another plug for my new friend: `as->`

I keep coming back to this example from the thread-last docs:

;; An example of using the "thread-last" macro to get
;; the sum of the first 10 even squares.
(->> (range)
     (map #(* % %))
     (filter even?)
     (take 10)
     (reduce +))

Now, I know you're always doing TDD and therefore, never need to avial yourself of any primitive debugging, but let's say a friend is in trouble and you want to help them out (before you do them an even bigger favor by teaching them TDD). So, you'd like to see, a word which here means invoke println on, the value of one of the intermediate transformations in the above threading operation.

(->> (range)
     (map #(* % %))
     (filter even?)
     (take 10)
     (println)     ;; returns nil :(
     (reduce +))

This does output the value of the intermediate transformation at the point of the (println), but it also results in (reduce + nil). This isn't catastrophic in this example, but bear with me.

Let's refactor to the 'thread-last' macro:

(as-> (range) $
      (map #(* % %) $)
      (filter even? $)
      (take 10 $)
      (reduce + $))

...which allows us to insert (do (println $) $) at any point without disturbing the threading of existing results through the forms. (Just don't insert it before the take 10 operation...)

(as-> (range) $
      (map #(* % %) $)
      (filter even? $)
      (take 10 $)
      (do (println $) $)   ;; OUTPUT: (0 4 16 36 64 100 144 196 256 324)
      (reduce + $)
      (do (println $) $))  ;; OUTPUT: 1140