Как скопировать массив в общий lisp?

Я хотел бы сделать копии своего 2D-массива, который выглядит как хороший, функциональный, неразрушающий способ обработки массивов. Что это за липкий способ сделать это?

Ответ 1

Я использую следующее, которое, я считаю, лучше, чем версия александрии:

(defun copy-array (array &key
                   (element-type (array-element-type array))
                   (fill-pointer (and (array-has-fill-pointer-p array)
                                      (fill-pointer array)))
                   (adjustable (adjustable-array-p array)))
  "Returns an undisplaced copy of ARRAY, with same fill-pointer and
adjustability (if any) as the original, unless overridden by the keyword
arguments."
  (let* ((dimensions (array-dimensions array))
         (new-array (make-array dimensions
                                :element-type element-type
                                :adjustable adjustable
                                :fill-pointer fill-pointer)))
    (dotimes (i (array-total-size array))
      (setf (row-major-aref new-array i)
            (row-major-aref array i)))
    new-array))

Проблема с версией александрии заключается в том, что adjust-array hack приводит к тому, что результат (по крайней мере, на SBCL) никогда не будет simple-array, который ожидают некоторые другие библиотеки (например, opticl). выше версия также была быстрее для меня.

Кто-то опубликовал очень похожую версию в другом библиотеке, но я забыл имена как человека, так и библиотеки.

Ответ 2

Общая Lisp библиотека Alexandria (устанавливается через quicklisp) включает реализацию copy-array для произвольных рангов и размеров:

(defun copy-array (array &key
                   (element-type (array-element-type array))
                   (fill-pointer (and (array-has-fill-pointer-p array)
                                      (fill-pointer array)))
                   (adjustable (adjustable-array-p array)))
  "Returns an undisplaced copy of ARRAY, with same fill-pointer and
adjustability (if any) as the original, unless overridden by the keyword
arguments. Performance depends on efficiency of general ADJUST-ARRAY in the
host lisp -- for most cases a special purpose copying function is likely to
perform better."
  (let ((dims (array-dimensions array)))
    ;; Dictionary entry for ADJUST-ARRAY requires adjusting a
    ;; displaced array to a non-displaced one to make a copy.
    (adjust-array
     (make-array dims
                 :element-type element-type :fill-pointer fill-pointer
                 :adjustable adjustable :displaced-to array)
     dims)))

Ответ 3

Это зависит от того, как представлен ваш 2D-массив, и какой вкус Lisp вы используете.

Если вы используете Common Lisp, то copy-seq может быть полезным.

Ответ 4

Если вы хотите делать что-то the nice, functional, nondestructive way, то почему вам даже нужно его скопировать?

  • если вы копируете его, чтобы обновить его, - тогда вы не выполняете его функциональным способом.

  • если вы делаете это функционально - тогда вам не нужна копия. Вы можете просто передать его везде и всюду.

Возможно, вы хотите его преобразовать. В этом случае вы можете использовать одну из Lisp многих чистых функций, таких как mapcar или filter.