Documentation
Commentary
The `loopy' macro is used to generate code for a loop, similar to `cl-loop'.
Unlike `cl-loop', `loopy' uses symbolic expressions instead of "clauses".
A simple usage of `cl-loop':
(cl-loop for i from 1 to 10
if (cl-evenp i) collect i into evens
else collect i into odds
end ; This `end' keyword is optional here.
finally return (list odds evens))
How it could be done using `loopy':
(loopy (numbers i 1 10)
(if (cl-evenp i)
(collect evens i)
(collect odds i))
(finally-return odds evens))
`loopy' supports destructuring for iteration commands like `list' and
accumulation commands like `sum' or `collect'.
;; Summing the nth elements of arrays:
;; => (8 10 12 14 16 18)
(loopy (list (list-elem1 list-elem2)
'(([1 2 3] [4 5 6])
([7 8 9] [10 11 12])))
(sum [sum1 sum2 sum3] list-elem1)
(sum [sum4 sum5 sum6] list-elem2)
(finally-return sum1 sum2 sum3 sum4 sum5 sum6))
;; Or, more simply:
;; => (8 10 12 14 16 18)
(loopy (list list-elem '(([1 2 3] [4 5 6])
([7 8 9] [10 11 12])))
(sum ([sum1 sum2 sum3] [sum4 sum5 sum6])
list-elem)
(finally-return sum1 sum2 sum3 sum4 sum5 sum6))
;; Separate the elements of sub-list:
;; => ((1 3) (2 4))
(loopy (list i '((1 2) (3 4)))
(collect (elem1 elem2) i)
(finally-return elem1 elem2))
The `loopy' macro is configurable and extensible. In addition to writing
one's own "loop commands" (such as `list' in the example below), by using
"flags", one can choose whether to instead use `pcase-let', `seq-let', or
even the Dash library for destructuring.
;; Use `pcase' to destructure array elements:
;; => ((1 2 3 4) (10 12 14) (11 13 15))
(loopy (flag pcase)
(array (or `(,car . ,cdr) digit)
[1 (10 . 11) 2 (12 . 13) 3 4 (14 . 15)])
(if digit
(collect digits digit)
(collect cars car)
(collect cdrs cdr))
(finally-return digits cars cdrs))
;; Using the default destructuring:
;; => ((1 2 3 4) (10 12 14) (11 13 15))
(loopy (array elem [1 (10 . 11) 2 (12 . 13) 3 4 (14 . 15)])
(if (numberp elem)
(collect digits elem)
(collect (cars . cdrs) elem))
(finally-return digits cars cdrs))
Variables like `cars', `cdrs', and `digits' in the example above are
automatically `let'-bound so as to not affect code outside of the loop.
`loopy' has arguments for binding (or not binding) variables, executing code
before/after the loop, executing code only if the loop completes, and for
setting the macro's return value (default `nil'). This is in addition to the
looping features themselves.
All of this makes `loopy' a useful and convenient choice for looping and
iteration.
That being said, Loopy is not yet feature complete. Please request features
or report problems in this project’s issues tracker
(<https://codeberg.org/okamsn/loopy/issues>). While most cases are covered,
full feature parity with some of the more niche uses of `cl-loop' is still
being worked on.
For more information, including the full list of loop commands and how to
extend the macro, see this package's comprehensive Info documentation under
the Info node `(loopy)'.
Consumers