(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)))
Array with initial content that is determined by function
-
12-10-2022 - |
Question
I'm trying to create a multidimensional array with initial content that is determined by a function. It is easy to do for any specified dimensionality of the array.
For example for 2x2 array:
(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))
Gives me #2A((0 1 2) (1 2 3)).
How do I generalize the macro for any dimensionality? For example for 2x3x5x6x7x8
(defparameter bla (array-generation + 2 3 5 6 7 8))
Solution
OTHER TIPS
You already have an answer, so I would just like to add this as food for thought. Three observations:
- It's not necessary for
array-generation
to be a macro; it can be a function. - It may be easier to initialise the array explicitly instead of generating a list for consumption by
:initial-contents
. - The default initial value for
from
is 0, so it can be left out.
(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)))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow