[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

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

シーケンス(sequence)型は、リスト、ベクタ、文字列というほかの三つの Lisp型の和集合であることを思い出してください。いいかえれば、任意のリストは シーケンスであり、任意のベクタはシーケンスであり、任意の文字列は シーケンスです。全てのシーケンスが共通してもつ性質は、順序づけられた要素の 集まりだということです。

配列(array)は、プリミティブなオブジェクトの一つで、要素ごとに スロットを持ちます。全ての要素は、一定の時間でアクセス可能ですが、 既存の配列の長さを変えることはできません。文字列とベクタは配列の 二つの型です。

リストは要素の並びですが、プリミティブなオブジェクトの一つ ではありません。リストはコンス・セルからなり、要素ごとに一つのセルが 割当てられています。n番目の要素を見つけるには、n番目の コンス・セルまで全て見なければならないので、リストの先頭から遠い要素ほど アクセスに時間がかかります。しかし、リストだと要素を追加することや 取り除くことができます。

次の図式は、これらの型の間の関係を示しています:

 
        ┌───────────────────┐
        │                                      │
        │          シーケンス                  │
        │┏━━━━┓┏━━━━━━━━━━━┓│
        │┃        ┃┃                      ┃│
        │┃ リスト ┃┃        配列          ┃│
        │┃        ┃┃┏━━━┓┏━━━━┓┃│
        │┃        ┃┃┃      ┃┃        ┃┃│
        │┗━━━━┛┃┃ベクタ┃┃ 文字列 ┃┃│
        │            ┃┗━━━┛┗━━━━┛┃│
        │            ┗━━━━━━━━━━━┛│
        └───────────────────┘
                                       

ベクタとリストの要素は、任意のLispオブジェクトで構いません。 文字列の要素は、全て文字です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 シーケンス

Emacs Lispでは、シーケンス(sequence)は、リスト、ベクタ、 文字列のいずれかです。全てのシーケンスが共通してもつ性質は、 順序づけられた要素の集まりだということです。 本節では、これらのシーケンスを受けつける関数を説明します。

Function: sequencep object

objectがリスト、ベクタ、文字列ならばtを、 そうでなければnilを返します。

Function: copy-sequence sequence

sequenceのコピーを返します。コピーは元のシーケンスと同じ型の オブジェクトで、同じ要素を同じ順序で持ちます。

コピーに新たな要素を格納しても、元のsequenceに影響しませんし、 その逆も同じです。けれども、作られた方のシーケンスの要素はコピーでは ありません。それらは元の要素と同一(eq)のものです。 したがって、コピーされたシーケンスでこれらの要素内に行なった変更は、 元のシーケンスでも見ることができます。

もしそのシーケンスがテキスト属性をもつ文字列であるならば、 コピーでの属性リスト自身もコピーであり、元の属性リストを共有するものでは ありません。けれども、属性の実際の値は共有されています。 See section テキスト属性

シーケンスをコピーするほかの方法については、 コンス・セルとリストの生成append文字列の生成concatベクタ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要素を置き換える。
(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)]
Function: length sequence

sequence中の要素の個数を返します。sequenceがコンス・セルで あっても、(最後のCDRnilではないので)それがリストではないならば、 wrong-type-argumentエラーが通知されます。

 
(length '(1 2 3))
    ⇒ 3
(length ())
    ⇒ 0
(length "foobar")
    ⇒ 6
(length [1 2 3])
    ⇒ 3
Function: elt sequence index

この関数は、sequenceの添字index番目の要素を返します。 正当なindexの値は整数で、範囲は0からsequenceの長さよりも 一つ小さい値までです。範囲外のindex値を指定すると、sequenceが リストのときはnilを返します。それ以外の場合は、 args-out-of-rangeエラーを発します。

 
(elt [1 2 3 4] 2)
     ⇒ 3
(elt '(1 2 3 4) 2)
     ⇒ 3
(char-to-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 section 配列に関する関数)と nth(see section リストの要素の参照)とを一般化したものです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 配列

配列(array)オブジェクトは、スロットを持ち、そこにほかのLisp オブジェクトを複数、格納できます。それらを配列要素と呼びます。 任意の配列要素は一定の時間でアクセスできます。それに対しリストの要素は、 そのリスト内の位置に比例したアクセス時間を要します。

配列作成の際は、それがいくつ要素をもつかを指定しなければなりません。 割当てられる空間の大きさは要素数に依存します。したがって、いったん作成した 配列の大きさを変更することは不可能です。要素の追加や削除はできません。 しかし、要素を異なる値で置き換えることはできます。

Emacsは、ともに1次元である二つの配列型、文字列(string)ベクタ(vector)を定義しています。ベクタは一般化された配列です。 つまり、その要素は任意のLispオブジェクトで構いません。文字列は、 その要素として文字(即ち、0から255までの整数)だけが許される、 特化した配列です。いずれの配列型も固有のリード構文を持ちます。 文字列型と、See section ベクタ型

いずれの配列も次の特性を持ちます:

原則的には、テキスト文字の配列が欲しい場合、文字列あるいはベクタの どちらでも構いません。しかし、実用的には、そのような場合は常に文字列を 選んでいます。それには四つ理由があります:

対照的に、(キー・シーケンスなどの)キーボード入力文字の配列に対しては、 ベクタであることが必要な場合もあります。というのも、多くの キーボード入力文字は、文字列に収まるような範囲の外にあるためです。 See section キー・シーケンス入力


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3 配列に関する関数

本節では、文字列とベクタを受けつける関数を説明します。

Function: arrayp object

この関数は、objectが配列(即ち、ベクタあるいは文字列)であるならば、 tを返します。

 
(arrayp [a])
⇒ t
(arrayp "asdf")
⇒ t
Function: aref array index

この関数は、arrayindex番目の要素を返します。 第1要素の添字は0です。

 
(setq primes [2 3 5 7 11 13])
     ⇒ [2 3 5 7 11 13]
(aref primes 4)
     ⇒ 11
(elt primes 4)
     ⇒ 11

(aref "abcdefg" 1)
     ⇒ 98           ; `b' は ASCII コード 98.

シーケンスにある関数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エラーとなります。

Function: fillarray array object

この関数は、objectarrayを埋めます。その結果、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 section シーケンス


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4 ベクタ

Lispにおける配列は、ほとんどの言語における配列同様、メモリの ひとかたまりからなり、要素には一定の時間でアクセスできます。 ベクタ(vector)は汎用の配列であり、その要素は任意のLispオブェクトで 構いません(これに対して、Emacs Lispでのほかの配列文字列(string)では、 その要素は文字でなければなりません)。ベクタはEmacs内で、 構文テーブル(整数のベクタ)として、obarray(シンボルのベクタ)として、 キーマップ(コマンドのベクタ)として使われています。 内部的にはさらに、バイトコンパイルされた関数表現の一部としても使われます。 そのような関数を印字すると、ベクタが中にあるのが見えます。

Emacs Lispでは、ベクタ要素の添字は0からはじまり、そこから順に数えて 行きます。

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

ベクタは、文字列や数同様に、評価に際しては定数とみなされます。 その評価結果は同じベクタです。評価もされないし、ベクタの要素を調べることさえ されません。See section 自己評価型形式

次に、これらの原則の例を示します。

 
(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 ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5 ベクタを操作する関数

ベクタに関係するいくつかの関数を挙げます:

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

この関数は、length個の要素からなる新しいベクタを返します。 各要素をobjectに初期化します。

 
(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もまた、引数として整数を許します。引数をその整数の 10進印字表現をなす数字文字列に変換し、それを元の整数の代わりに使用します。 この機能は削除する予定なので、使ってはなりません。すでにこの機能を 使っているならば、直ちにプログラムを変更してください!こういった方法で整数を 数字に変換したいならば、format(see section 文字列の書式変換) あるいはnumber-to-string(see section 文字と文字列間の変換)を使ってください。

これ以外の結合用関数については、マッピング関数にあるmapconcat文字列の生成にあるconcatコンス・セルとリストの生成にある appendを参照してください。

append関数でベクタを同じ要素をもつリストに変換する方法があります (see section コンス・セルとリストの生成):

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

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Yasutaka SHINDOH on September, 29 2006 using texi2html 1.76.