1

Antik手册的4.3.3 Iterate有这个代码示例:

 (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

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

4

1 回答 1

2

注意:我花了一些时间才能够运行 REPL 文档中的示例。reader 宏的行分隔符是符号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 修复迭代扩展以正确递增

于 2013-06-15T04:30:06.337 回答