具有索引列表的访问数组

时间:2013-10-29 12:17:12

标签: arrays macros common-lisp

我想访问索引在列表中的数组。我们将此实用程序称为arefl,其定义如下:

(arefl array '(x y z ...)) equals (aref array x y z ...) 

我的目标是创建一些在任何大小的矩阵上运行的通用函数。

我没有用宏来实现这样的事情而只是aref。我最接近的是:

(defmacro arefl (array is)
  "Access array by a list of indices"
  `(apply #'aref (cons ,array ,is)))

有效,实际上它也适用于(setf (arefl array is) value),但编译器(至少sbcl)会发出警告,告诉我我正在重新定义setf(我猜){ {1}}。警告是:

apply

-

有更好的方法吗?我正在寻找一个适用于; in: DEFUN (SETF AREFL**) ; (SETF (APPLY #'AREF ARRAY (REDUCE 'CONS ARGS :FROM-END T)) NEW-VALUE) ; --> LET* MULTIPLE-VALUE-BIND LET APPLY MULTIPLE-VALUE-CALL ; ==> ; #'(SETF AREF) ; ; caught STYLE-WARNING: ; defining as a SETF function a name that already has a SETF macro: ; (SETF AREF) ; ; compilation unit finished ; caught 1 STYLE-WARNING condition 的实现,并且不需要调用setf之类的其他函数,也不需要执行任何apply

2 个答案:

答案 0 :(得分:2)

好的,define-setf-expander对此有点矫枉过正。

(defun arefl (array list)
  (apply #'aref array list))
(defun (setf arefl) (x array list)
  (setf (apply #'aref array list) x))

请参阅“将表单应用为地点”:http://clhs.lisp.se/Body/05_abe.htm

答案 1 :(得分:2)

首先,虽然我认识到你说过

  

我正在寻找一个适用于setf的实现,并且不需要调用apply之类的其他函数,也不需要执行任何cons

但是,你可以在这里使用apply 'aref不需要cons,因为只有{{} 1}}的最终参数需要是一个列表。这意味着以下所有内容都是等效的:

apply

最重要的是,如果您想避免调用(aref array 0 1) (apply 'aref (list array 0 1)) (apply 'aref array (list 0 1)) (apply 'aref array 0 (list 1)) (apply 'aref array 0 1 '()) ,则表示您可以执行

cons

您也可以使用(apply 'aref array indices) (虽然您必须使用setf,而不是#'array):

'array

由于(setf (apply #'aref array indices) new-value) 适用于此处,您只需制作applyaref*函数(与(setf aref*)类似):

list*

其中(defun aref* (array &rest args)   (apply 'aref array (reduce 'cons args :from-end t)))               (defun (setf aref*) (new-value array &rest args)   (setf (apply #'aref array (reduce 'cons args :from-end t)) new-value)) 用于支持spreadable argument list designators(reduce 'cons args :from-end t)使用apply。使用此惯用法,您可以将完全相同类型的参数传递给您可以在(aref* ...)中使用的(apply #'aref ...)。这可能比你描述的用例复杂一点,但这意味着你不必专门描述aref*所采用的各种参数,你可以简单地说(就像{{1的文档一样) ({1}}的args是一个可扩展的参数列表指示符,而applyaref*应用于args。