91ea751ccd9f

Add do-vector
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Mon, 24 May 2021 01:05:13 -0400
parents acf6a1d4de2e
children 6740e201e636
branches/tags (none)
files src/control-flow.lisp src/package.lisp

Changes

--- 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`.
 
--- 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