本地“macrolet”中未知的参数类型

Aro*_*oob 1 macros common-lisp

在这个示例代码中

(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)))
Run Code Online (Sandbox Code Playgroud)

我尝试访问一个一维固定的矩阵(当前在0坐标处)。所以(loop-over-dim mat 0) ;; => (1 4 7 10 13); 至少这是意图。

但是,当尝试编译它时,SBCL 告诉我

值 ARY 不是 ARRAY 类型

错误上方的样式警告表示loop-over-dim未使用的参数。但是它们用于macrolet.

那么,除了风格上的考虑,为什么我会得到ARY不是数组的错误?

我已经尝试移动let*外部macrolet但具有相同的结果(错误)。

我也试过包裹loop-over-dim在一个eval-when,但没有骰子。

也许macrolet(或一般的宏)是(是)这个工作的错误工具?(参见Hyperspec

[...] 但如果局部宏定义引用在该词法环境中可见的任何局部变量或函数绑定,则后果是未定义的。

)

Syl*_*ter 5

宏语法上工作,因此ad获取绑定到符号arydim和当然不是别的比符号,这将是评估阵列和数字宏已完成其工作,并扩展代码实际运行后变量。

扩展可以在编译时在调用函数之前完成。您应该完全松开宏并在函数中执行逻辑运行时。

  • @Aroob 是的,但这就是`apply` 的用途。最后一个参数的长度限制与调用中的参数数量限制相同。例如。如果`apply` 失败,你的宏就会失败。您可以评估 `CALL-ARGUMENTS-LIMIT` 以查看您可能有多少个参数,并且保证至少为 50。在 64 位 SBCL 中,限制超过 4 quintillion,但我想 50 就足够了 99%的程序员需要。 (2认同)