[iterate-devel] destructively altering elements
Hello, I'm doing some matrix operations and would like to use iterate for going through my matrices element wise. Writing an driver to do this was pretty easy (great tools and manual!), but it doesn't allow me to alter entries in my matrix. Therefore I was wondering if there is some easy way to write something like (FOR el IN-MATRIX vec) that expands to (symbol-macrolet ((el (aref vec row-index col-index))) (... body...)) If there is no way to do this, could you please provide me with some pointers about how I can contribute to add such feature? Thanks in advance Albert Note: I asked this question on comp.lang.lisp and was redirected here. For the corresponding thread see http://groups.google.de/group/comp.lang.lisp/browse_thread/thread/007e487752... -- Albert Krewinkel <krewink (at) inb.uni-luebeck.de> University of Luebeck, Institute for Neuro- and Bioinformatics http://www.inb.uni-luebeck.de/~krewink/
Hi, Albert Krewinkel wrote:
I'm doing some matrix operations and would like to use iterate for going through my matrices element wise. Writing an driver to do this was pretty easy (great tools and manual!), but it doesn't allow me to alter entries in my matrix.
(symbol-macrolet ((el (aref vec row-index col-index))) (... body...)) Macrolet is a possibility, but what about writing a driver that provides access to the 2 index variables, modeled after in-vector? (for x in-vector foo with-index i) (for e in-matrix foo with-indices (i j)) (setf (aref foo i j) bar)
BTW, how do you use Iterate to walk across a 2-dimensional thing like a matrix? This would likely involve 2 nested iterations, so any single clause does not provide a complete solution?!? Regards, Jorg Hohle
On Wed, Jun 27, 2007 at 12:48:48PM +0200, Hoehle, Joerg-Cyril wrote:
Albert Krewinkel wrote:
(symbol-macrolet ((el (aref vec row-index col-index))) (... body...)) Macrolet is a possibility, but what about writing a driver that provides access to the 2 index variables, modeled after in-vector? (for x in-vector foo with-index i) (for e in-matrix foo with-indices (i j)) (setf (aref foo i j) bar)
That sure is a good way to do this. Maybe you are right, and the python zen "explizit is better than implicit" applies to this situation as well. But I just feel like it's more verbose than necessary.
BTW, how do you use Iterate to walk across a 2-dimensional thing like a matrix? This would likely involve 2 nested iterations, so any single clause does not provide a complete solution?!?
Regards, Jorg Hohle
A single clause is sufficient for my needs, see code below. It's a quick hack and for testing only, so it's plain ugly. One of my concernes is efficiency. It might be premature optimization, but still: If I do (let ((v (vector 65 42 23 5 105))) (iter (for el in-vector v with-index i) (setf (aref v i) 1)) v) the expansion code will contain (setq el (aref...)). Having a variable to be set to a new value in every iteration, although not needed, doesn't seem to be optimal. Of course I could just iterate using the index, but wouldn't I loose some nice abstractions this way? Thanks for your help Albert <code style="ugly"> (defmacro-driver (FOR var IN-MATRIX matrix &optional WITH-INDICES (indices (list (gensym "ROW") (gensym "COL"))) BY (row-or-column 'column)) (let ((mat (gensym "MAT")) (kwd (if generate 'generate 'for))) (ecase row-or-column ((or column col) (let ((num-cols (gensym "COLS")) (num-rows (gensym "ROWS")) (col-index (car indices)) (row-index (cadr indices))) `(progn ;nlisp (with ,mat = (val ,matrix)) (initially (setq ,col-index 0)) (with ,mat = ,matrix) (with ,num-cols = (array-dimension ,mat 1)) (with ,num-rows = (array-dimension ,mat 0)) (with ,row-index = -1) (generate ,col-index next (incf ,col-index)) (,kwd ,var next (progn (incf ,row-index) (when (>= ,row-index ,num-rows) (if (>= (next ,col-index) ,num-cols) (terminate) (setf ,row-index 0))) (aref ,mat ,row-index ,col-index)))))) ('row (let ((end (gensym "END-INDEX")) (index (gensym "INDEX"))) `(progn ;nlisp (with ,mat = (val ,matrix)) (with ,mat = ,matrix) (with ,end = (array-total-size ,mat)) (with ,index = -1) (,kwd ,var next (progn (incf ,index) (if (>= ,index ,end) (terminate)) (row-major-aref ,mat ,index))))))))) </code>
Hi again, Albert Krewinkel wrote:
(for e in-matrix foo with-indices (i j)) That sure is a good way to do this. Maybe you are right, and the python zen "explizit is better than implicit" applies to this situation as well. But I just feel like it's more verbose than necessary.
To me it seems like "Iterate zen". Otherwise you are with things like Series. Actually, naming things simplifies (or make possible) some complex loops.
(iter (for el in-vector v with-index i) (setf (aref v i) 1)) the expansion code will contain (setq el (aref...)). The Iterate zen is for i index-of-vector. See manual. That would not invoke aref.
The careful reader of the manual might expect (for nil in-vector ... with-index i) to avoid aref given a clever implementation, however Iterate is not Loop, so that construct does not work (yet?) with Iterate. BTW, do users consider this a bug? (iter (for nil in-vector "abc") (counting t)) => error (loop for nil across "abc" count t) => 3 (loop for nil in '(1 2 3) count t) => 3 etc. However (iter (for nil in-package "CL" :external-only t) (counting t)) => 978 probably as a hazard of the implementation.
It's a quick hack and for testing only (ecase row-or-column ((or column col) ('row Your code may appear to work for you, but your case expression is subtly broken. Please try (for el in-vector v by OR) (for el in-vector v by QUOTE)
Regards, Jorg Hohle.
Hello once more, On Wed, Jun 27, 2007 at 04:11:36PM +0200, Hoehle, Joerg-Cyril wrote:
Albert Krewinkel wrote:
(for e in-matrix foo with-indices (i j)) That sure is a good way to do this. Maybe you are right, and the python zen "explizit is better than implicit" applies to this situation as well. But I just feel like it's more verbose than necessary.
To me it seems like "Iterate zen". Otherwise you are with things like Series. Actually, naming things simplifies (or make possible) some complex loops.
Seems reasonable; I'll try to adopt this.
(iter (for el in-vector v with-index i) (setf (aref v i) 1)) the expansion code will contain (setq el (aref...)). The Iterate zen is for i index-of-vector. See manual. That would not invoke aref.
The careful reader of the manual might expect (for nil in-vector ... with-index i) to avoid aref given a clever implementation, however Iterate is not Loop, so that construct does not work (yet?) with Iterate.
Looks like I have to re-read the manual more carefully.
Your code may appear to work for you, but your case expression is subtly broken. Please try (for el in-vector v by OR) (for el in-vector v by QUOTE) D'OH! Thanks for pointing this out.
I will rewrite the driver using the `indices-of..' idiom. I don't really see the advantages yet, but that's probably due to a lack of experience on my side. Thanks again the help and for your time, Best Albert
participants (2)
-
Albert Krewinkel
-
Hoehle, Joerg-Cyril