Как вы копируете массив в общий lisp? - PullRequest
10 голосов
/ 27 октября 2011

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

Ответы [ 4 ]

15 голосов
/ 27 октября 2011

ОБНОВЛЕНИЕ : В настоящее время Александрия имеет 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."
  (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 хак приводит к тому, что результат (по крайней мере, в SBCL) никогда не будет simple-array, чего ожидают некоторые другие библиотеки (например, opticl). выше версия также была быстрее для меня.

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

3 голосов
/ 27 октября 2011

Библиотека Common Lisp Александрия (устанавливается через 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)))
1 голос
/ 27 октября 2011

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

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

0 голосов
/ 29 октября 2011

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

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

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

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

...