Lispにおける配列の使い方

そういや今までLispで配列を使ったことがなかった.Lispのリストはデータ構造でいえば線形リストなので要素の追加や挿入が楽だけれど,規模が大きくなるとo(n)で時間がかかる.配列の場合は配列ポインタからのオフセットで表現されるのでランダムアクセスが可能になる.
配列は直接生成することもできるけれど,make-array関数を使うのが無難.make-array関数にはいくつかオプションがある.

; 1次元配列の生成
(make-array 5)
#(nil nil nil nil nil)

; 初期値の設定.足りないとnilが入る
(make-array 4 :initial-contents '(4 6))
#(4 6 nil nil)

; あぶれると無視される
(make-array 3 :initial-contents '(4 6 4 9))
#(4 6 4)

; 2次元配列の生成.2次元以上はリストで指定
(make-array '(2 3) :initial-contents '((1 2 3) (4 5 6)))
#2A((1 2 3) (4 5 6))

; デフォルト値の設定
(make-array '(2 3) :initial-element 1)
#2A((1 1 1) (1 1 1))

; 配列の要素の指定
(make-array 3 :element-type 'character
	      :initial-contents '(#\x #\Y #\z))
"xYz"

; 配列の要素と違う値を入力するとエラーが出る
(make-array 3 :element-type 'character
  	      :initial-contents '(1 2 3))
不正なデータ型です: 1: character

(make-array 3 :element-type 'float
  	      :initial-contents '(1.1 2.2 3.3))
#(1.1 2.2 3.3)

最後の方にあるとおり,element-typeで配列の要素を指定することができる.ちょっと調べたけれどふたつしかわからなかった.

'character  ; 文字
'fixnum     ; 整数型
'float      ; 小数


配列の内容取得は以下のようにarefで出来る.設定する場合はgethashと同様にsetfを用いる.

(aref #2A((1 2 3) (4 5 6)) 0 2)
3

; #A(1 2 3)という配列の最初の値を5に変更する
(let ((x (make-array 3 :initial-contents '(1 2 3))))
  (setf (aref x 0) 5)
  x)
#(5 2 3)

2次元以上も同じ要領でできる(はず).2次元以上はそんなに使うことないと思うけれど.


ちなみに配列の前についている#2Aというのは「2次元の配列ですよー」という意味.なので,1次元配列の場合#1Aになるのだが,1Aを省略することができる.

(aref #1A(1 2 3) 2)
3
(aref #(1 2 3) 2)
3


よしよし,配列とハッシュが使えれば(更に構造体使えるし),かなり楽にプログラム書けますな.