66fc93caa1c6

Add iterate `FOR var MODULO divisor` driver
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Tue, 22 Nov 2016 20:07:42 +0000
parents 344ee2fa239e
children 1c23d5693192
branches/tags (none)
files losh.lisp package.lisp

Changes

--- a/losh.lisp	Mon Nov 21 11:10:49 2016 +0000
+++ b/losh.lisp	Tue Nov 22 20:07:42 2016 +0000
@@ -707,6 +707,48 @@
 
 
 ;;;; Iterate ------------------------------------------------------------------
+(defmacro expand-iterate-sequence-keywords ()
+  '(list
+    :from iterate::from
+    :upfrom iterate::upfrom
+    :downfrom iterate::downfrom
+    :to iterate::to
+    :downto iterate::downto
+    :above iterate::above
+    :below iterate::below
+    :by iterate::by
+    :with-index iterate::with-index))
+
+
+(defmacro-driver (FOR var MODULO divisor &sequence)
+  "Iterate numerically modulo `divisor`.
+
+  This driver iterates just like the vanilla `for`, but each resulting value
+  will be modulo'ed by `divisor` before being bound to `var`.
+
+  Note that the modulo doesn't affect the *iteration*, it just affects the
+  variable you *see*.  It is as if you had written two clauses:
+
+    (for temp :from foo :to bar)
+    (for var = (mod temp divisor))
+
+  Example:
+
+    (iterate (for i            :from 0 :to 20 :by 3) (collect i))
+    (0 3 6 9 12 15 18)
+
+    (iterate (for i :modulo 10 :from 0 :to 20 :by 3) (collect i))
+    (0 3 6 9  2  5  8)
+
+  "
+  (let ((kwd (if generate 'generate 'for)))
+    (with-gensyms (i d)
+      `(progn
+        (with ,d = ,divisor)
+        (generate ,i ,@(expand-iterate-sequence-keywords))
+        (,kwd ,var next (mod (next ,i) ,d))))))
+
+
 (defmacro-driver (FOR var PAIRS-OF-LIST list)
   "Iterate over the all pairs of the (including (last . first)).
 
--- a/package.lisp	Mon Nov 21 11:10:49 2016 +0000
+++ b/package.lisp	Tue Nov 22 20:07:42 2016 +0000
@@ -122,25 +122,27 @@
   (:use :iterate) ; need this for iterate's `for` symbol fuckery
   (:documentation "Custom `iterate` drivers and clauses.")
   (:export
-    :pairs-of-list
+    :across-flat-array
     :averaging
+    :cycling
+    :for-nested
+    :in-array
+    :in-lists
+    :in-sequences
+    :in-whatever
+    :index-of-flat-array
     :into
-    :timing
-    :since-start-into
+    :macroexpand-iterate
+    :modulo
+    :pairs-of-list
     :per-iteration-into
     :real-time
     :run-time
-    :in-lists
-    :in-sequences
-    :in-whatever
-    :in-array
-    :across-flat-array
-    :index-of-flat-array
-    :cycling
-    :for-nested
+    :since-start-into
+    :skip-origin
+    :timing
     :within-radius
-    :skip-origin
-    :macroexpand-iterate))
+    ))
 
 (defpackage :losh.hash-tables
   (:documentation "Utilities for operating on hash tables.")