注意:我花了一些时间才能够运行 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 修复迭代扩展以正确递增