1c23d5693192

Add `every-nth` iterate driver
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Tue, 22 Nov 2016 21:40:35 +0000
parents 66fc93caa1c6
children d5f5a30b7eee
branches/tags (none)
files losh.lisp package.lisp

Changes

--- a/losh.lisp	Tue Nov 22 20:07:42 2016 +0000
+++ b/losh.lisp	Tue Nov 22 21:40:35 2016 +0000
@@ -1210,6 +1210,56 @@
         (next ,control)))))
 
 
+(defmacro-driver (FOR var EVERY-NTH n DO form)
+  "Iterate `var` numerically modulo `n` and run `form` every `n`th iteration.
+
+  The driver can be used to perform an action every N times through the loop.
+
+  `var` itself will be a counter that counts up from to to `n - 1`.
+
+  `generate` is supported.
+
+  Example:
+
+    (iterate (for i :from 1 :to 7)
+             (print `(iteration ,i))
+             (for tick :every-nth 3 :do (print 'beep))
+             (print `(tick ,tick)) (terpri))
+    ; =>
+    (ITERATION 1)
+    (TICK 0)
+
+    (ITERATION 2)
+    (TICK 1)
+
+    (ITERATION 3)
+    BEEP
+    (TICK 2)
+
+    (ITERATION 4)
+    (TICK 0)
+
+    (ITERATION 5)
+    (TICK 1)
+
+    (ITERATION 6)
+    BEEP
+    (TICK 2)
+
+    (ITERATION 7)
+    (TICK 0)
+
+  "
+  (let ((kwd (if generate 'generate 'for)))
+    (with-gensyms (counter limit)
+      `(progn
+        (with ,limit = ,n)
+        (generate ,counter :modulo ,limit :from 0)
+        (,kwd ,var :next (prog1 (next ,counter)
+                           (when (= ,counter (1- ,limit))
+                             ,form)))))))
+
+
 (defun keywordize-clause (clause)
   (iterate
     (for (k v . nil) :on clause :by #'cddr)
--- a/package.lisp	Tue Nov 22 20:07:42 2016 +0000
+++ b/package.lisp	Tue Nov 22 21:40:35 2016 +0000
@@ -125,6 +125,7 @@
     :across-flat-array
     :averaging
     :cycling
+    :every-nth
     :for-nested
     :in-array
     :in-lists