Antik Iterate扩展在迭代中重复矩阵元素

时间:2013-06-15 03:03:38

标签: common-lisp

4.3.3 Iterate的{p> Antik manual有以下代码示例:

 (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

第1行第0列中的元素似乎要重复。这是一个小故障还是有原因的? 我在Emacs中运行代码得到了类似的结果,我无法在他们的邮件列表中找到信息或搜索Google的原因。 对此的答案将有助于其他人尝试迭代矩阵和向量的元素。

1 个答案:

答案 0 :(得分:2)

注意:我花了一些时间才能从REPL的文档中运行示例。阅读器宏的行分隔符是符号grid:^,因此代码示例实际上是:

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

#m阅读器宏似乎创建了预期的网格类型。

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

所以似乎任何问题都可能来自Iterate扩展的实现。我们可以宏观扩展第二种形式,看看它变成了什么,并试图弄清楚是否出现了问题。

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))

它实际上看起来非常像迭代到达行的末尾并且还有更多行要进行,而不是仅仅递增行计数器并将列计数器设置为零(对于下一行)并且去回到循环的顶部,再次使用行的最后一列中的元素执行循环体。看了这个扩展,我们可以通过尝试一些不同的网格来测试这个假设:

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 

对我来说这看起来像个错误。

更新(2013/06/24)

我刚刚从Antik-devel列表收到了已修复错误的电子邮件:

  

e85d75dc44a1修复迭代扩展以正确递增