[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6. シーケンス、配列、ベクトル

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Sequences%20Arrays%20Vectors"
"texi/elisp21/シーケンス、配列、ベクトル"へのコメント(無し)

シーケンス(sequence)型とは、Lispの2つの異なる型の和であることを 思い出してください。 いいかえれば、任意のリストはシーケンスであり、 任意の配列もシーケンスです。 すべてのシーケンスに共通する性質は、 それぞれ、要素の順序付けた集まりであるということです。

配列(array)は、各要素ごとに1つ1つスロットを用意してある 単一の基本オブジェクトです。 すべての要素は一定時間内に参照できますが、既存の配列の長さは変更できません。 文字列、ベクトル、文字テーブル、ブールベクトルは、配列型の4つの型です。

リストは、要素を並べたものですが、 単一の基本オブジェクトではありません。 コンスセルから作られていて、1つの要素あたり1つのセルがあります。 n番目の要素を探すには、n個のコンスセルを調べる必要があるので、 リストの先頭から遠い要素を参照するには余計に時間がかかります。 しかし、リストには要素を追加したり削除したりできます。

以下の図は、これらの型の関係を示します。

 
     ┌────────────────────────┐
     │      シーケンス             │
     │┌───┐ ┌───────────────┐ │
     ││   │ │               │ │
     ││リスト│ │      配列       │ │
     ││   │ │ ┌────┐ ┌───┐  │ │
     ││   │ │ │    │ │   |  │ │
     │└───┘ │ │ベクトル│ │文字列|  │ │
     │      │ │    │ │   |  │ │
     │      │ └────┘ └───┘  │ │
     │      │ ┌────┐ ┌────┐ │ │
     │      │ │文字  │ │ブール │ │ │
     │      │ │テーブル│ │ベクトル│ │ │
     │      │ └────┘ └────┘ │ │
     │      └───────────────┘ │
     └────────────────────────┘

ベクトルやリストの要素は、どんなLispオブジェクトでもかまいません。 文字列の要素はすべて文字です。



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.1 シーケンス

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Sequence%20Functions"
"texi/elisp21/シーケンス"へのコメント(無し)

Emacs Lispでは、シーケンス(sequence)とはリストか配列のことです。 すべてのシーケンスに共通する性質は、 要素の順序付けた集まりであるということです。 本節では任意のシーケンスを受け付ける関数を説明します。

Function: sequencep object
objectが、リスト、ベクトル、あるいは、文字列ならばtを返し、 さもなければnilを返す。

Function: length sequence
この関数はsequence内の要素の個数を返す。 sequenceが(最後のCDRがnilではないため) リストではないコンスセルであると、 エラーwrong-type-argumentを通知する。

関連する関数safe-lengthについては、see 節 5.4 リストの要素の参照

 
(length '(1 2 3))
    => 3
(length ())
    => 0
(length "foobar")
    => 6
(length [1 2 3])
    => 3
(length (make-bool-vector 5 nil))
    => 5

Function: elt sequence index
この関数はindexで添字付けされるsequenceの要素を返す。 indexの正当な値は、0からsequenceの長さより1小さい範囲の 整数である。 sequenceがリストである場合には、 範囲外のindexに対してはnilを返す。 さもなければエラーargs-out-of-rangeを引き起こす。

 
(elt [1 2 3 4] 2)
     => 3
(elt '(1 2 3 4) 2)
     => 3
;; stringを用いてeltが返す文字を明確にする
(string (elt "1234" 2))
     => "3"
(elt [1 2 3 4] 4)
     error--> Args out of range: [1 2 3 4], 4
(elt [1 2 3 4] -1)
     error--> Args out of range: [1 2 3 4], -1

この関数は、aref(see 節 6.3 配列操作関数)や nth(see 節 5.4 リストの要素の参照)を汎用にしたものである。

Function: copy-sequence sequence
sequenceのコピーを返す。 コピーは、もとのシーケンスと同じ型のオブジェクトであり、 同じ要素が同じ順序で入っている。

コピーに新たな要素を格納しても、もとのsequenceには影響せず、 その逆もそうである。 しかし、新たなシーケンスの要素はコピーしていない。 つまり、それらはもとの要素と同一(eq)である。 したがって、シーケンスのコピーにおいて、 それらの要素の内部を変更すると、もとのシーケンスでもその変更がわかる。

シーケンスがテキスト属性を持つ文字列である場合には、 コピーの中の属性リストそのものもコピーであり、 もとの属性リストを共有するのではない。 しかし、属性の実際の値は共有される。

シーケンスをコピーする別の方法については、 5.5 コンスセルとリストの構築append4.3 文字列の作成concat6.4 ベクトルvconcatを参照。

 
(setq bar '(1 2))
     => (1 2)
(setq x (vector 'foo bar))
     => [foo (1 2)]
(setq y (copy-sequence x))
     => [foo (1 2)]

(eq x y)
     => nil
(equal x y)
     => t
(eq (elt x 1) (elt y 1))
     => t

;; 1つのシーケンスの1つの要素を置き換える
(aset x 0 'quux)
x => [quux (1 2)]
y => [foo (1 2)]

;; 共有された要素の内部を修正する
(setcar (aref x 1) 69)
x => [quux (69 2)]
y => [foo (69 2)]



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.2 配列

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Arrays"
"texi/elisp21/配列"へのコメント(無し)

配列(array)オブジェクトには、配列の要素と呼ばれる Lispオブジェクトを保持するためのスロットがいくつかあります。 配列の任意の要素は一定時間で参照できます。 一方、リストの要素の参照には、 リスト内でのその要素の位置に比例した時間が必要です。

Emacsには4つの型の配列があり、すべて1次元です。 文字列(strings)、ベクトル(vectors)、 ブールベクトル(bool-vectors)、文字テーブル(char-tables)です。 ベクトルは汎用の配列であり、 その要素は任意のLispオブジェクトでかまいません。 文字列は特化された配列であり、その要素は文字(つまり、0から255までの整数)で ある必要があります。 配列のそれぞれの型には、独自の入力構文があります。 2.3.8 文字列型とSee 節 2.3.9 ベクトル型

配列の4つの型すべてには、以下の性質があります。

文字テーブル以外の配列を作成するときには、 その長さを指定する必要があります。 文字テーブルの長さは指定できません。 というのは、その長さは文字コードの範囲で決まるからです。

原理的には、テキスト文字の配列が必要ならば文字列かベクトルを使います。 実用上は、以下の4つの理由から、そのような場合には文字列を使います。

一方、(キー列のような)キーボード入力文字の配列には、 ベクトルが必要です。 というのは、キーボード入力文字の多くは、文字列に納まる範囲外だからです。 See 節 20.6.1 キー列の入力



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.3 配列操作関数

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Array%20Functions"
"texi/elisp21/配列操作関数"へのコメント(無し)

本節では任意の配列型を受け付ける関数を説明します。

Function: arrayp object
この関数はobjectが配列 (つまり、ベクトル、文字列、ブールベクトル、あるいは、文字テーブル)ならば、 tを返す。

 
(arrayp [a])
     => t
(arrayp "asdf")
     => t
(arrayp (syntax-table))    ;; 文字テーブル
     => t

Function: aref array index
この関数はarrayindex番目の要素を返す。 最初の要素の添字は0。

 
(setq primes [2 3 5 7 11 13])
     => [2 3 5 7 11 13]
(aref primes 4)
     => 11
(aref "abcdefg" 1)
     => 98           ; `b'は、ASCIIコード98

6.1 シーケンスの関数eltも参照。

Function: aset array index object
この関数は配列arrayindex番目の要素にobjectを設定する。 objectを返す。

 
(setq w [foo bar baz])
     => [foo bar baz]
(aset w 0 'fu)
     => fu
w
     => [fu bar baz]

(setq x "asdfasfd")
     => "asdfasfd"
(aset x 3 ?Z)
     => 90
x
     => "asdZasfd"

arrayが文字列であり、かつ、objectが文字でなければ、 結果はエラーwrong-type-argumentとなる。 arrayが文字列であり、かつ、objectが文字であっても、 現在(aref object index)に保存されている文字のバイト数と objectが使うバイト数が異なれば、やはり、エラーとなる。 see 節 32.7 文字の分割

Function: fillarray array object
この関数は、配列arrayobjectで埋め、 arrayの各要素がobjectとなるようにする。 arrayを返す。

 
(setq a [a b c d e f g])
     => [a b c d e f g]
(fillarray a 0)
     => [0 0 0 0 0 0 0]
a
     => [0 0 0 0 0 0 0]
(setq s "When in the course")
     => "When in the course"
(fillarray s ?-)
     => "------------------"

arrayが文字列であり、かつ、objectが文字でなければ、 結果はエラーwrong-type-argumentになる。

配列であることが既知のオブジェクトに対しては、 汎用のシーケンス関数copy-sequencelengthがしばしば有用です。 See 節 6.1 シーケンス



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.4 ベクトル

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Vectors"
"texi/elisp21/ベクトル"へのコメント(無し)

Lispの配列は、ほとんどの言語の配列と同様に、 その要素を一定時間で参照可能なメモリのブロックです。 ベクトル(vector)は指定長の汎用配列です。 その要素はどんなLispオブジェクトでもかまいません。 (対照的に、文字列は要素としては文字だけを保持する。) Emacsでは、オブジェクト配列obarray(シンボルのベクトル)、 キーマップ(コマンドのベクトル)の一部にベクトルを使っています。 これらは、内部的には、バイトコード関数の表現の一部にも使っています。 そのような関数を表示すると、その中にベクトルがあるのがわかります。

Emacs Lispでは、ベクトルの要素の添字は0から始まります。

ベクトルは要素を角括弧で囲んで表示します。 したがって、要素がシンボルabaであるベクトルは、 [a b a]と表示されます。 Lispへの入力では同じようにベクトルを書きます。

文字列や数と同様に、評価上、ベクトルは定数とみなします。 それを評価した結果は、同じベクトルです。 この評価では、ベクトルの要素を評価したり調べたりはしません。

以下は、これらの原理を例示するものです。

 
(setq avector [1 two '(three) "four" [five]])
     => [1 two (quote (three)) "four" [five]]
(eval avector)
     => [1 two (quote (three)) "four" [five]]
(eq avector (eval avector))
     => t



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.5 ベクトル向け関数

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Vector%20Functions"
"texi/elisp21/ベクトル向け関数"へのコメント(無し)

ベクトルに関連した関数はつぎのとおりです。

Function: vectorp object
この関数は、objectがベクトルならばtを返す。

 
(vectorp [a])
     => t
(vectorp "asdf")
     => nil

Function: vector &rest objects
この関数は、引数objectsを要素とするベクトルを作成しそれを返す。

 
(vector 'foo 23 [bar baz] "rats")
     => [foo 23 [bar baz] "rats"]
(vector)
     => []

Function: make-vector length object
この関数は、各要素をobjectに初期化した length個の要素から成る新たなベクトルを返す。

 
(setq sleepy (make-vector 9 'Z))
     => [Z Z Z Z Z Z Z Z Z]

Function: vconcat &rest sequences
この関数は、sequencesのすべての要素を入れた新たなベクトルを返す。 引数sequencesは、リスト、ベクトル、文字列を含む任意の配列でよい。 sequencesを指定しないと空ベクトルを返す。

その値は、既存のベクトルとeqでない新たに作成したベクトルである。

 
(setq a (vconcat '(A B C) '(D E F)))
     => [A B C D E F]
(eq a (vconcat a))
     => nil
(vconcat)
     => []
(vconcat [A B C] "aa" '(foo (6 7)))
     => [A B C 97 97 foo (6 7)]

関数vconcatは、引数としてバイトコード関数でも受け付ける。 これは、バイトコード関数オブジェクトの全内容を簡単に参照できるように するための特別な機能である。 see 節 15.6 バイトコード関数オブジェクト

関数vconcatは、引数として整数も受け付ける。 整数はその10進の表示表現の文字列に変換してから、 その文字列を整数のかわりに使う。 この機能を使わないでほしい。 削除する予定である。 読者がこの機能を使っていたら、今すぐプログラムを直すこと! 整数をこのような10進数に変換する正しい方法は、 format(see 節 4.7 文字列の書式付け)や number-to-string(see 節 4.6 文字と文字列の変換)を使うことである。

他の連結関数については、 11.6 マップ関数mapconcat4.3 文字列の作成concat5.5 コンスセルとリストの構築appendを参照。

関数appendは、ベクトルを同じ要素から成るリストへ変換する便利な方法です (see 節 5.5 コンスセルとリストの構築)。

 
(setq avector [1 two (quote (three)) "four" [five]])
     => [1 two (quote (three)) "four" [five]]
(append avector nil)
     => (1 two (quote (three)) "four" [five])



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.6 文字テーブル

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Char-Tables"
"texi/elisp21/文字テーブル"へのコメント(無し)

文字テーブルはベクトルによく似ていますが、 文字コードで添字付けする点が異なります。 修飾子を伴わない任意の正当な文字コードは、文字テーブルの添字に使えます。 文字テーブルの要素は、任意の配列のように、arefasetで 参照できます。 さらに、文字テーブルでは、 特定の文字コードには対応しない追加データを保持するための追加スロットを 保持できます。 評価時には、文字テーブルは定数です。

各文字テーブルには、シンボルであるサブタイプ(subtype)があります。 サブタイプには2つの目的があります。 異なる使い方をする文字テーブルを区別するためと、 追加スロットの個数を制御するためです。 たとえば、表示テーブルはサブタイプがdisplay-tableである 文字テーブルであり、 構文テーブルはサブタイプがsyntax-tableである文字テーブルです。 正当なサブタイプには、char-table-extra-slots属性があるはずで、 その値は0から10までの整数です。 この整数が文字テーブルの追加スロットの個数を指定します。

文字テーブルは、別の文字テーブルであるを持てます。 その場合、特定の文字cに対する文字テーブルの指定がnilのときには、 親において指定された値を継承します。 いいかえれば、char-table自体にnilを指定してあると、 (aref char-table c)は、 char-tableの親の値を返します。

文字テーブルは、デフォルト値も持てます。 その場合、文字テーブルが指定する値がnilであると、 (aref char-table c)はデフォルト値を返します。

Function: make-char-table subtype &optional init
サブタイプがsubtypeである新たに作成した文字テーブルを返す。 各要素をinitで初期化する。 なお、initのデフォルトはnilである。 文字テーブル作成後には、文字テーブルのサブタイプは変更できない。

文字テーブルの長さを指定する引数はない。 なぜなら、すべての文字テーブルでは、 任意の正当な文字コードを添字として使えるからである。

Function: char-table-p object
この関数は、objectが文字テーブルならばtを返し、 さもなければnilを返す。

Function: char-table-subtype char-table
この関数はchar-tableのサブタイプを表すシンボルを返す。

Function: set-char-table-default char-table new-default
この関数はchar-tableのデフォルト値をnew-defaultにする。

文字テーブルのデフォルト値を参照するための特別な関数はない。 それには(char-table-range char-table nil)を使う。

Function: char-table-parent char-table
この関数はchar-tableの親を返す。 親は、nilであるか他の文字テーブルである。

Function: set-char-table-parent char-table new-parent
この関数はchar-tableの親をnew-parentにする。

Function: char-table-extra-slot char-table n
この関数はchar-tableの追加スロットnの内容を返す。 文字テーブル内の追加スロットの個数はそのサブタイプで決まる。

Function: set-char-table-extra-slot char-table n value
この関数はchar-tableの追加スロットnvalueを格納する。

文字テーブルでは、1つの文字コードに対して1つの要素値を指定できます。 また、文字集合全体に対して1つの値を指定することもできます。

Function: char-table-range char-table range
これは、char-tableにおいて文字範囲rangeに指定されている値を返す。 rangeとして可能なものは以下のとおり。

nil
デフォルト値を指す。

char
charが正当な文字コードであると仮定して) 文字charに対する要素を指す。

charset
文字集合charset全体に対して指定してある値を指す (see 節 32.5 文字集合)。

generic-char
文字集合に対する汎用文字を表す。 引数として汎用文字を指定することは、文字集合名を指定することと同値。 汎用文字の説明は、see 節 32.7 文字の分割

Function: set-char-table-range char-table range value
この関数は文字範囲rangeに対するchar-tableの値を設定する。 rangeとして可能なものは以下のとおり。

nil
デフォルト値を指す。

t
文字コードの範囲全体を指す。

char
charが正当な文字コードであると仮定して) 文字charに対する要素を指す。

charset
文字集合charset全体に対して指定してある値を指す (see 節 32.5 文字集合)。

generic-char
文字集合に対する汎用文字を表す。 引数として汎用文字を指定することは、文字集合名を指定することと同値。 汎用文字の説明は、see 節 32.7 文字の分割

Function: map-char-table function char-table
この関数は、char-tableの各要素についてfunctionを呼び出す。 functionをキーと値の2つの引数で呼び出す。 キーはchar-table-rangeに対する可能なrange引数であり、 正当な文字か汎用文字である。 値は(char-table-range char-table key)である。

全体として、functionに渡すキー・値の対は、 char-tableに格納されたすべての値を表す。

戻り値はつねにnilである。 この関数が有用であるようにするには、 functionには副作用があるべきである。 たとえば、つぎは構文テーブルの各要素の調べ方である。

 
(let (accumulator)
  (map-char-table
   #'(lambda (key value)
       (setq accumulator
             (cons (list key value) accumulator)))
   (syntax-table))
  accumulator)
=>
((475008 nil) (474880 nil) (474752 nil) (474624 nil)
 ... (5 (3)) (4 (3)) (3 (3)) (2 (3)) (1 (3)) (0 (3)))



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

6.7 ブールベクトル

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Bool-Vectors"
"texi/elisp21/ブールベクトル"へのコメント(無し)

ブールベクトルはベクトルによく似ていますが、 tnilの値だけを保存できる点が異なります。 ブールベクトルの要素にnil以外の値を保存しようとすると、 その効果はtを保存することになります。 すべての配列と同様に、ブールベクトルの添字は0から始まり、 ブールベクトルをいったん作成すると長さは変更できません。 評価時には、ブールベクトルは定数です。

ブールベクトルを操作する特別な関数は2つあります。 それに加えて、他の種類の配列を扱う関数でも操作できます。

Function: make-bool-vector length initial
initialに初期化した長さlengthの新たなブールベクトルを返す。

Function: bool-vector-p object
objectがブールベクトルであればtを返し、 さもなければnilを返す。


[ << ] [ >> ]           [表紙] [目次] [索引] [検索] [上端 / 下端]