Antik Iterate extension repeats matrix element in

2019-08-12 07:49发布

问题:

4.3.3 Iterate of the Antik manual has this code example:

 (defparameter m1 #m(1 2 3 ^ 0 6 8))
 (iter:iter (iter:for e :matrix-element m1) (princ e) (princ " "))

;Output:
 1.0 2.0 3.0 0.0 0.0 6.0 8.0

The element in Row 1 Column 0 Seems to be repeated. Is this a glitch or is there a reason for it? I get similar results running the code in Emacs and I can't find info on their mailing list or searching Google for a reason. An answer to this would help others attempting to iterate over the elements of matrices and vectors.

回答1:

Note: It took me a few moments to be able to run the example from the documentation at the REPL. The row separator for the reader macro is the symbol grid:^, so the code example is actually:

(defparameter m1 #m(1 2 3 grid:^ 0 6 8))
(iter:iter (iter:for e :matrix-element m1) (princ e) (princ " "))

The #m reader macro seems to create the kind of grid that would be expected.

CL-USER> m1
#2A((1.0 2.0 3.0) (0.0 6.0 8.0))

so it seems like any problem is probably coming from the implementation of the extension to Iterate. We can macroexpand the second form and see what it's being turned into, and try to figure out whether something has gone awry.

CL-USER> (macroexpand '(iter:iter (iter:for e :matrix-element m1) (princ e) (princ " ")))
(LET* ((#:M1182 M1)                                        ; grid
       (#:ROW-INDEX1178 0)                                 ; i
       (#:COL-INDEX1179 0)                                 ; j 
       (#:ROW-SIZE1180 (FIRST (GRID:DIMENSIONS #:M1182)))  ; nrows
       (#:COL-SIZE1181 (SECOND (GRID:DIMENSIONS #:M1182))) ; ncols
       (E NIL))
  (BLOCK NIL
    (TAGBODY
      (PROGN)
     LOOP-TOP-NIL
      (PROGN
       (PROGN
        (SETQ E
                (IF (>= #:ROW-INDEX1178 #:ROW-SIZE1180)      ; if done with rows
                    (GO LOOP-END-NIL)                        ; then then the loop
                    (IF (>= #:COL-INDEX1179 #:COL-SIZE1181)  ; else if done with the columns
                        (PROGN
                         (SETQ #:COL-INDEX1179 0)            ; reset j = 0 for next row
                         (LET* ((#:G1184 1)
                                (#:NEW1183 (+ #:ROW-INDEX1178 #:G1184))) ; next row, i++
                           (SETQ #:ROW-INDEX1178 #:NEW1183))
                         (IF (>= #:ROW-INDEX1178 #:ROW-SIZE1180) ; if *now* done with rows
                             (GO LOOP-END-NIL)                   ; end the loop, 
                             (GRID:AREF #:M1182 #:ROW-INDEX1178  ; otherwise E 
                                        #:COL-INDEX1179)))       ; E = grid[i][0] (why?)
                                                                 ; shouldn't we (go loop-top-nil) ?

                        (PROG1                                   ; otherwise, not done with columns
                            (GRID:AREF #:M1182 #:ROW-INDEX1178 #:COL-INDEX1179) ; E = grid[i][j]
                          (LET* ((#:G1186 1)
                                 (#:NEW1185 (+ #:COL-INDEX1179 #:G1186)))
                            (SETQ #:COL-INDEX1179 #:NEW1185))))))) ; j++
       (PRINC E)
       (PRINC " "))
      (PROGN)
      (GO LOOP-TOP-NIL)
     LOOP-END-NIL
      (PROGN))
    NIL))

It actually looks very much like when the iteration gets to the end of a row and there are still more rows to go, rather than just incrementing the row counter and setting the column counter to zero (for the next row) and going back to the top of the loop, executes the loop body again with the element in the last column of the row. Having looked at this expansion, we can test this hypothesis by trying with some different grids:

CL-USER> (iter:iter (iter:for e :matrix-element #m(1 2 grid:^ 3 4 grid:^ 5 6)) (princ e) (princ " "))
1.0 2.0 3.0 3.0 4.0 5.0 5.0 6.0

CL-USER> (iter:iter (iter:for e :matrix-element #m(1 grid:^ 2 grid:^ 3)) (princ e) (princ " "))
1.0 2.0 2.0 3.0 3.0 

This looks like a bug to me.

Update (2013/06/24)

I just received email from the Antik-devel list that the bug has been fixed:

e85d75dc44a1 Fix iterate extension to increment properly



标签: common-lisp