# HG changeset patch
# User Steve Losh <steve@stevelosh.com>
# Date 1621832713 14400
# Node ID 91ea751ccd9f1b6ace12946efb7a434b22b3adbb
# Parent  acf6a1d4de2e9a202373d37df55a8d5ce05ad7e9
Add do-vector

diff -r acf6a1d4de2e -r 91ea751ccd9f src/control-flow.lisp
--- a/src/control-flow.lisp	Sun May 23 16:53:10 2021 -0400
+++ b/src/control-flow.lisp	Mon May 24 01:05:13 2021 -0400
@@ -431,6 +431,38 @@
   `(dotimes (,(gensym) ,n)
      ,@body))
 
+(defmacro do-vector ((var-or-vars vector) &body body)
+  "Iterate over `vector`, performing `body` with `var-or-vars` bound.
+
+  `var-or-vars` can be one of the following:
+
+  * `value-symbol`
+  * `(value-symbol)`
+  * `(index-symbol value-symbol)`
+
+  Successive elements of `vector` will be bound to `value-symbol` while `body`
+  is executed.  If `index-symbol` is given, the current index will be bound to
+  it.
+
+  Returns `nil`.
+
+  "
+  (setf var-or-vars (alexandria:ensure-list var-or-vars))
+  (alexandria:once-only (vector)
+    (let ((i nil)
+          (v nil)
+          (len (gensym "LEN")))
+      (ecase (length var-or-vars)
+        (1 (setf i (gensym "I")
+                 v (first var-or-vars)))
+        (2 (setf i (first var-or-vars)
+                 v (second var-or-vars))))
+      `(do ((,len (length ,vector))
+            (,i 0 (1+ ,i)))
+         ((>= ,i ,len))
+         (let ((,v (aref ,vector ,i)))
+           ,@body)))))
+
 (defmacro do-range (ranges &body body)
   "Perform `body` on the given `ranges`.
 
diff -r acf6a1d4de2e -r 91ea751ccd9f src/package.lisp
--- a/src/package.lisp	Sun May 23 16:53:10 2021 -0400
+++ b/src/package.lisp	Mon May 24 01:05:13 2021 -0400
@@ -242,7 +242,8 @@
     :do-repeat
     :do-range
     :do-irange
-    :do-file))
+    :do-file
+    :do-vector))
 
 
 (defpackage :losh.math