配列 - Alexandria

概要

このページではCommon Lispの汎用ユーティリティであるAlexandriaの配列に関する型と関数を紹介します。

配列に関する型

Common Lispではdeftypeマクロでオリジナルの「型」を定義することができます。型はクラスや構造体を定義するときに付随して定義されますが、型単独で定義することも可能です。(詳しくはANSI Common Lisp仕様入門の第4章「型とクラス」を参照してください。)

Alexandriaでは配列に関する型が2種類定められています。
Type: array-index
配列の要素番号を示す型で、0以上指定の数未満を意味します。
Type: array-length
配列の要素番号を示す型で、0以上指定の数以下を意味します。
2つの方の違いは「未満」か「以下」です。例えば、3つの要素を持つ配列の要素番号は0, 1, 2のいずれかであり、3未満となりますが、要素数は3です。

以下で例を示します。
;; あらかじめ型をインポートしておく
(shadowing-import 'alexandria:array-index)
; => T
(shadowing-import 'alexandria:array-length)
; => T

;; 未満と以下で動作が異なる点に注意
(typep 3 '(array-index 3))
; => NIL

(typep 3 '(array-length 3))
; => T

型を指定するとcheck-typeマクロを使うことができるため、例外処理を簡単に記述することができるのが便利です。詳しくは仕様入門の第4章「型とクラス」のcheck-typeマクロの節を参照してください。

copy-array関数: 配列のコピー

ANSI Common Lispでは配列を完全にコピーできる関数は用意されていません。Common Lispの配列にはフィルポインタなどの様々な機能が組み込まれており、自分で配列をコピーするのは意外と大変です。

そこでAlexandriaにはcopy-arrayという標準仕様にもありそうな関数が定義されています。
(defparameter *array* (make-array 10 :element-type 'fixnum 
                                     :initial-element 0
                                     :adjustable t
                                     :fill-pointer 3))
; => *ARRAY*

(equalp *array* (alexandria:copy-array *array*))
; => T
ただし、:adjustable:fill-pointerを付けた配列へのアクセスはsimple-vectorへのアクセスに比べてかなり遅くなります。複雑な配列のコピーは自分の行う計算をよく考えて使用してください。

0 件のコメント :

コメントを投稿