| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
シーケンス(sequence)型とは、Lispの2つの異なる型の和であることを 思い出してください。 いいかえれば、任意のリストはシーケンスであり、 任意の配列もシーケンスです。 すべてのシーケンスに共通する性質は、 それぞれ、要素の順序付けた集まりであるということです。
配列(array)は、各要素ごとに1つ1つスロットを用意してある 単一の基本オブジェクトです。 すべての要素は一定時間内に参照できますが、既存の配列の長さは変更できません。 文字列、ベクトル、文字テーブル、ブールベクトルは、配列型の4つの型です。
リストは、要素を並べたものですが、 単一の基本オブジェクトではありません。 コンスセルから作られていて、1つの要素あたり1つのセルがあります。 n番目の要素を探すには、n個のコンスセルを調べる必要があるので、 リストの先頭から遠い要素を参照するには余計に時間がかかります。 しかし、リストには要素を追加したり削除したりできます。
以下の図は、これらの型の関係を示します。
┌────────────────────────┐ │ シーケンス │ │┌───┐ ┌───────────────┐ │ ││ │ │ │ │ ││リスト│ │ 配列 │ │ ││ │ │ ┌────┐ ┌───┐ │ │ ││ │ │ │ │ │ | │ │ │└───┘ │ │ベクトル│ │文字列| │ │ │ │ │ │ │ | │ │ │ │ └────┘ └───┘ │ │ │ │ ┌────┐ ┌────┐ │ │ │ │ │文字 │ │ブール │ │ │ │ │ │テーブル│ │ベクトル│ │ │ │ │ └────┘ └────┘ │ │ │ └───────────────┘ │ └────────────────────────┘ |
ベクトルやリストの要素は、どんなLispオブジェクトでもかまいません。 文字列の要素はすべて文字です。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
Emacs Lispでは、シーケンス(sequence)とはリストか配列のことです。 すべてのシーケンスに共通する性質は、 要素の順序付けた集まりであるということです。 本節では任意のシーケンスを受け付ける関数を説明します。
tを返し、 さもなければnilを返す。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
|
nilを返す。 さもなければエラーargs-out-of-rangeを引き起こす。
(elt [1 2 3 4] 2)
=> 3
(elt '(1 2 3 4) 2)
=> 3
;;
|
この関数は、aref(see 節 6.3 配列操作関数)や nth(see 節 5.4 リストの要素の参照)を汎用にしたものである。
コピーに新たな要素を格納しても、もとのsequenceには影響せず、 その逆もそうである。 しかし、新たなシーケンスの要素はコピーしていない。 つまり、それらはもとの要素と同一(eq)である。 したがって、シーケンスのコピーにおいて、 それらの要素の内部を変更すると、もとのシーケンスでもその変更がわかる。
シーケンスがテキスト属性を持つ文字列である場合には、 コピーの中の属性リストそのものもコピーであり、 もとの属性リストを共有するのではない。 しかし、属性の実際の値は共有される。
シーケンスをコピーする別の方法については、 5.5 コンスセルとリストの構築のappend、4.3 文字列の作成のconcat、 6.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 ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
配列(array)オブジェクトには、配列の要素と呼ばれる Lispオブジェクトを保持するためのスロットがいくつかあります。 配列の任意の要素は一定時間で参照できます。 一方、リストの要素の参照には、 リスト内でのその要素の位置に比例した時間が必要です。
Emacsには4つの型の配列があり、すべて1次元です。 文字列(strings)、ベクトル(vectors)、 ブールベクトル(bool-vectors)、文字テーブル(char-tables)です。 ベクトルは汎用の配列であり、 その要素は任意のLispオブジェクトでかまいません。 文字列は特化された配列であり、その要素は文字(つまり、0から255までの整数)で ある必要があります。 配列のそれぞれの型には、独自の入力構文があります。 2.3.8 文字列型とSee 節 2.3.9 ベクトル型。
配列の4つの型すべてには、以下の性質があります。
arefやasetで行う (see 節 6.3 配列操作関数)。文字テーブル以外の配列を作成するときには、 その長さを指定する必要があります。 文字テーブルの長さは指定できません。 というのは、その長さは文字コードの範囲で決まるからです。
原理的には、テキスト文字の配列が必要ならば文字列かベクトルを使います。 実用上は、以下の4つの理由から、そのような場合には文字列を使います。
一方、(キー列のような)キーボード入力文字の配列には、 ベクトルが必要です。 というのは、キーボード入力文字の多くは、文字列に納まる範囲外だからです。 See 節 20.6.1 キー列の入力。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
本節では任意の配列型を受け付ける関数を説明します。
tを返す。
(arrayp [a])
=> t
(arrayp "asdf")
=> t
(arrayp (syntax-table)) ;; 文字テーブル
=> t
|
(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も参照。
(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 文字の分割。
(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-sequenceやlengthがしばしば有用です。 See 節 6.1 シーケンス。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
Lispの配列は、ほとんどの言語の配列と同様に、 その要素を一定時間で参照可能なメモリのブロックです。 ベクトル(vector)は指定長の汎用配列です。 その要素はどんなLispオブジェクトでもかまいません。 (対照的に、文字列は要素としては文字だけを保持する。) Emacsでは、オブジェクト配列obarray(シンボルのベクトル)、 キーマップ(コマンドのベクトル)の一部にベクトルを使っています。 これらは、内部的には、バイトコード関数の表現の一部にも使っています。 そのような関数を表示すると、その中にベクトルがあるのがわかります。
Emacs Lispでは、ベクトルの要素の添字は0から始まります。
ベクトルは要素を角括弧で囲んで表示します。 したがって、要素がシンボルa、b、aであるベクトルは、 [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 ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
ベクトルに関連した関数はつぎのとおりです。
tを返す。
(vectorp [a])
=> t
(vectorp "asdf")
=> nil
|
(vector 'foo 23 [bar baz] "rats")
=> [foo 23 [bar baz] "rats"]
(vector)
=> []
|
(setq sleepy (make-vector 9 'Z))
=> [Z Z Z Z Z Z Z Z Z]
|
その値は、既存のベクトルと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 マップ関数のmapconcat、 4.3 文字列の作成のconcat、 5.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 ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
文字テーブルはベクトルによく似ていますが、 文字コードで添字付けする点が異なります。 修飾子を伴わない任意の正当な文字コードは、文字テーブルの添字に使えます。 文字テーブルの要素は、任意の配列のように、arefやasetで 参照できます。 さらに、文字テーブルでは、 特定の文字コードには対応しない追加データを保持するための追加スロットを 保持できます。 評価時には、文字テーブルは定数です。
各文字テーブルには、シンボルであるサブタイプ(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)はデフォルト値を返します。
nilである。 文字テーブル作成後には、文字テーブルのサブタイプは変更できない。
文字テーブルの長さを指定する引数はない。 なぜなら、すべての文字テーブルでは、 任意の正当な文字コードを添字として使えるからである。
tを返し、 さもなければnilを返す。文字テーブルのデフォルト値を参照するための特別な関数はない。 それには(char-table-range char-table nil)を使う。
nilであるか他の文字テーブルである。文字テーブルでは、1つの文字コードに対して1つの要素値を指定できます。 また、文字集合全体に対して1つの値を指定することもできます。
nilniltchar-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 ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |
ブールベクトルはベクトルによく似ていますが、 tとnilの値だけを保存できる点が異なります。 ブールベクトルの要素にnil以外の値を保存しようとすると、 その効果はtを保存することになります。 すべての配列と同様に、ブールベクトルの添字は0から始まり、 ブールベクトルをいったん作成すると長さは変更できません。 評価時には、ブールベクトルは定数です。
ブールベクトルを操作する特別な関数は2つあります。 それに加えて、他の種類の配列を扱う関数でも操作できます。
tを返し、 さもなければnilを返す。| [ << ] | [ >> ] | [表紙] | [目次] | [索引] | [検索] [上端 / 下端] [?] |