在此示例代码中
(defvar mat (make-array (list 5 3)
:initial-contents '((1 2 3)
(4 5 6)
(7 8 9)
(10 11 12)
(13 14 15))))
(defun mk-idx (dims dim)
(loop
for i below (length dims)
if (= i dim) collect 1
else collect 0))
(defun loop-over-dim (ary dim)
(macrolet ((expan (a d)
(let* ((dims (array-dimensions a))
(dim-max (nth d dims))
(sel (mk-idx dims d))
(i (gensym)))
`(loop
for ,i below ,dim-max
collect (aref ,a ,@(substitute i 1 sel))))))
(expan ary dim)))
我尝试访问一维固定(当前位于0
坐标处)的矩阵。所以(loop-over-dim mat 0) ;; => (1 4 7 10 13)
;至少那是目的。
但是,当尝试对其进行编译时,SBCL告诉我
值 ARY 不是类型 阵列
错误上方的样式警告指出loop-over-dim
的参数未使用。但是它们用于macrolet
的绑定中。
因此,除了样式方面的考虑之外,为什么我还会收到错误消息ARY
不是数组?
我已经尝试将let*
移到macrolet
之外,但结果相同(错误)。
我还尝试将loop-over-dim
包装在eval-when
内,但没有骰子。
也许macrolet
(或一般的宏)是该工作的错误工具?
(请参见Hyperspec
[...],但是如果局部宏定义引用了在该词汇环境中可见的任何局部变量或函数绑定,则后果是不确定的。
)
答案 0 :(得分:4)
宏在语法上起作用,因此a
和d
绑定到符号ary
和dim
上,并且当然除了符号以外,它们都是变量宏完成工作并且扩展的代码实际运行后,对数组和数字求值。
扩展可以在编译时完成,而无需调用该函数。您应该完全松开宏并在函数中进行逻辑运行时。
答案 1 :(得分:1)
宏看到代码。您无法询问源代码,将来它将拥有什么绑定。
您可以仅调用DESCRIBE来查看a
的值。
a
具有符号ary
作为值。 array-dimensions
期望将实际数组作为参数而不是符号。
CL-USER 8 > (defun loop-over-dim (ary dim)
(macrolet ((expan (a d)
(describe a)
nil))
(expan ary dim)))
LOOP-OVER-DIM
CL-USER 9 > (compile 'loop-over-dim)
ARY is a SYMBOL
NAME "ARY"
VALUE #<unbound value>
FUNCTION #<unbound function>
PLIST NIL
PACKAGE #<The COMMON-LISP-USER package, 115/256 internal, 0/4 external>