Hacker News new | ask | show | jobs
by gyim 3570 days ago
I haven't used the LOOP macro in CL, but the for macro in Clojure is also very powerful and (imho) very readable.

My take on the 'versify' example in 4 lines:

    (for [book book-order
          chapter (range 1 1000) :when (get-in bible [book (str chapter)])
          verse (range 1 1000) :when (get-in bible [book (str chapter) (str verse)])]
      [book chapter verse (get-in bible [book (str chapter) (str verse)])])
Notice that a single "for" can iterate in a multi-level structure. You can also use :let if you don't want to call (get-in) multiple times (which makes the code shorter, but more redundant and less efficient)
1 comments

I use CL/Scheme/Clojure at work. I generally prefer comprehension style ('for' in Clojure, srfi-42 in Scheme) but sometimes CL's loop let me save a few nestings.

One of such patterns is when I have to accumulate multiple kind of things while I zip through the input. Somewhat contrived example: You have a hashtable that maps integer key to a list of strings. You want to scan it just once and build two lists, strings associated with odd keys and strings associated with even keys.

    ;; populate input 
    (defvar input (make-hash-table :test 'eql))
    (setf (gethash 1 input) '("ichi" "hi"))
    (setf (gethash 2 input) '("ni" "fu"))
    (setf (gethash 3 input) '("san" "mi"))
    (setf (gethash 4 input) '("yon" "shi" "yo"))
    (setf (gethash 5 input) '("go" "itsu"))

    ;; loop
    (loop for k being each hash-key in input
       when (oddp k) append (gethash k input) into odds 
       when (evenp k) append (gethash k input) into evens 
       finally (return (values odds evens)))
    ; => ("go" "itsu" "san" "mi" "ichi" "hi") and ("yon" "shi" "yo" "ni" "fu")
You surely know this but for other people interested:

1. You could add "using (hash-value v)" in the iteration clause to directly have the value (no gethash).

2. There is maphash too.

Right! I tried to construct a terse example in hurry but apparently missed the mark. Usually loop comes handy when conditions and the way to extract values gets more complicated.