プログラムで配列を定義する - lisp-cookbook-ja/common-lisp GitHub Wiki

配列

プログラム中で配列を定義する

プログラム中で配列(一次元配列=>ベクタ)を得るには vector が利用できます。

(vector "foo" "bar" "baz")
;=> #("foo" "bar" "baz")

また、直に#()を用いて記述することも可能です。#( はリーダーマクロで#(から)までで構成される要素を含む単純ベクタとしてリーダーに読まれます。また、10進の数値を取ることができ、指定した要素より少ない場合はエラー、多い場合は最後の要素が長さを満すまで繰り返されます。 クオートは付ける必要はありません

#("foo" "bar" "baz")
;=> #("foo" "bar" "baz")

#2("foo" "bar" "baz")
;>>> error

#10("foo" "bar" "baz")
;=> #("foo" "bar" "baz" "baz" "baz" "baz" "baz" "baz" "baz" "baz")

また、バッククオート記法も利用可能です。

(let ((foo 1) (bar 2) (baz '(3 4)))
  `#(,foo ,bar ,@baz))
;=> #(1 2 3 4)

ちょっと細かい注記: vectorを使う例と#()を使う例は、結果として同じような値が得られますが、 意味的に違いがあります。

  • (vector x ...) はその式が実行される度に、新たな配列のインスタンスが作られます。
  • #(x ...) はその式が読み込まれた時に一度だけ、配列のインスタンスが作られます。 (特にあらかじめコンパイルした場合、配列はコンパイルされたコードの一部になります)。

前者はコンストラクタ呼び出し、後者はリテラルと言うこともできます。 (バッククオートの場合、基本的にはvectorなどを使った呼び出しへと展開されますが、 処理系依存なので例えばコンパイラが不変であると証明できる部分については リテラル扱いになるかもしれません。)

(defun vec1 () (vector 1 2 3))
(defun vec2 () #(1 2 3))

(eq (vec1) (vec1))  ;=> NIL
(eq (vec2) (vec2))  ;=> T