Reputation: 13
I am interested in numerical analysis and have recently began a love affair with Common LISP. I have found my thought processeses strongly influenced by years of more imperative style programming, so I am on a quest to develop a more lispy approach. A common theme for those on the LISP path, I presume.
Anyway, reading through CLTL2 it is stated that vectors can be accessed in constant time, whereas accessing a list is done in linear time (sec. 2.5.1). One can then (setf (apply #'aref *some-vector* idx) new-value)
to set one place of a vector. My two-part question is:
a. Is there a way to get several values of an array by giving a list indices, without having to loop through the list? E.g., something akin to a correct version of (map 'array #'aref *some-array* idx-list)
.
b. Is there a way to set the values of some elements of an array in the same spirit as above? It would be ideal to be able to apply a function (via an adequately defined map
, or to reduce
it, etc.) to a list of values extracted from arrays for, say, sampling and interpolation.
I would also appreciate any comments regarding array operations in general and numerical computing in particular (pointers to a tutorial or book, some mailing list, common pitfalls, when to use lists or other data structures instead, etc.).
Cheers.
Upvotes: 1
Views: 598
Reputation: 48659
I'm not sure why you want to avoid looping, since a function like MAP
must loop anyway.
But you can use MAP
, in combination with a function that creates a cyclic list, e.g.
(defun cycle (x)
(let ((result (list x)))
(setf (cdr result) result)
result))
(defun multiple-aref (array indices)
(map 'vector #'aref (cycle array) indices))
(multiple-aref '#(a b c d e f g) '(1 3 5))
=> #(B D F)
(cycle array)
creates the infinite list (array array array array ...)
. But MAP
still works because it only examines an many elements as there are in the shortest list it is given (in this case '(1 2 3)
).
Upvotes: 0
Reputation: 3930
a.
You can map to get to get the values by index like this:
(map 'vector #'(lambda (idx) (aref *some-array* idx)) idx-list)
Note that this works only for one-dimensional arrays. A more-than-one-dimensional version would look like this:
(map 'vector #'(lambda (idx) (apply #'aref *some-array* idx)) idx-list)
Upvotes: 2
Reputation: 14335
b. You can assign several consecutive values at once:
(setf (subseq vector start end) values)
Upvotes: 3