具有由函数确定的初始内容的数组

时间:2014-02-15 06:50:31

标签: macros multidimensional-array lisp common-lisp

我正在尝试创建一个多维数组,其初始内容由函数确定。对于数组的任何指定维度,都很容易做到。

例如2x2数组:

(defmacro array-generation (fun &rest size-dimensions)
 (let ((a (gensym)) 
       (b (gensym))) 
    `(make-array ',size-dimensions
       :initial-contents 
          (loop for ,a from 0 below (first ',size-dimensions) by 1           
       collect 
          (loop for ,b from 0 below (second ',size-dimensions) by 1
       collect (,fun  ,a ,b))))))

(defparameter bla (array-generation + 2 3))

给我#2A((0 1 2)(1 2 3))。

如何针对任何维度推广宏? 例如,对于2x3x5x6x7x8

(defparameter bla (array-generation + 2 3 5 6 7 8))

2 个答案:

答案 0 :(得分:1)

(defmacro array-generation (fun &rest dims)
  (let ((syms (loop :repeat (length dims) :collect (gensym))))
    (reduce (lambda (x y) (append x (list y)))
            (mapcar (lambda (sym dim)
                      `(loop for ,sym from 0 below ,dim by 1 collect))
                    syms dims)
            :initial-value (cons fun syms)
            :from-end t)))

答案 1 :(得分:0)

你已经有了答案,所以我想把它作为思考的食物。三点意见:

  • array-generation没有必要成为一个宏;它可以是一种功能。
  • 显式初始化数组可能更容易,而不是生成:initial-contents消耗的列表。
  • from的默认初始值为0,因此可以省略。
(defun array-generation (fn &rest dimensions)
  (let ((array (make-array dimensions)))
    (labels ((init (dims indices)
               (if (null dims)
                   (setf (apply #'aref array indices) (apply fn indices))
                   (loop for i below (first dims) do
                         (init (rest dims) (cons i indices))))))
      (init (reverse dimensions) nil)
      array)))