4 ms·
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 nestin
by shiro 10y ago
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")
- junke 10y agoYou 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.
- shiro 10y agoRight! 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.