¥chapter{配列とリスト}

配列(array)は、複数個のオブジェクトをコレクションとして扱う最も基本的なデータ構造です。Konohaでは、配列はArray} クラスとして実現されています。クラス名は、単にArray}であるが、JavaのArrayList} と同様に、可変長配列（Growing Array）であり、リストやスタックなどのデータ構造を扱う場合にも活用できます。

== 配列と型}

Konohaの配列型は、2種類のスタイルがあります。ひとつは、Array}型で、任意の型の要素をもつ配列です。もうひとつは、CやJavaでおなじみのT}[]|スタイルの型で、T}型の要素をもつ配列です。両者は、一見全くことなるようにみえるが、ともにArray}のいわゆる総称型の別名で、Array<|Any>|}とArray<|T>|}です。基本的な性質は大きく変わらない。

本書では、Konoha スタイルで２種類の配列型を併有して書くが、実際のソースコードでは古典的な配列スタイル、総称型スタイルのどれを利用しても構いません。

¥begin{source}
Konoha          配列            総称型
Array           Any[]           Array<Any>           
int[]           int[]           Array<int>
String[]        String[]        Array<String>   
T[]             T[]             Array<T>
¥end{source}

¥subsubsection{Unboxされた配列: int}{¥tt []} float}{¥tt []}}

プログラマの立場からみれば、int}{¥tt []} と Array<|int>|}は区別なく利用できます。ただし、これはあくまでも見かけ上の話です。Konoha 内部では、より正確に言えば、整数(int}と浮動小数点数(float})はunbox された形で整数要素を格納する専用のクラス実装に切り替えています。ちなみにboolean}{¥tt []}は、現在のところ unboxされていない。

=== Array}とObject}{¥tt []}の違い}

Object} は、全てのオブジェクトの上位クラスです。そのため、Object}{¥tt []}は、Array}と同様に任意の型のオブジェクトを要素に持つことができます。ただし、「第 ¥ref{dynamic_style} 章　ダイナミック言語スタイル」で述べるとおり、Object} とAny}は、キャストの取扱いが異なるため、両者には注意すべき違いが生じる。

まず、Object}{¥tt []}の方であるが、基本的に Java の場合と同じ振る舞いをする。ただし、配列の要素型は、コンパイルした時点では Object}型なので、次の例のとおり、実行時に扱う要素が明らかにString}型であっても、明示的なダウンキャストが必要となります。

{{{
>>> String[] o = ["naruto", "sakura"];
>>> typeof(o[0])                // 要素型はObject
Object
>>> String s = (String)o[0];    // ダウンキャストが必要
>>> s
"naruto"
}}}

これに対し、Any}型は、実行時に動的な型検証が入るため、静的なキャストは不要になります。こちらの方が便利な反面、気づかないうちにダウンキャストや型変換を行っているため、実行効率が落ちることがあります。

{{{
>>> Any[] a = ["naruto", "sakura"];
>>> typeof(a[0])                // 要素型は動的
Any
>>> String s = a[0];            // キャストは不要
>>> s
"naruto"
}}}

=== null}要素*}

Konohaの配列は、null}値を配列要素に持つことができない。ただし、Any}型はいかなる場合でも null}値を求めるため、Array}型のみnull}を要素にもつことができます。

{{{
>>> String[] s = ["naruto"];
>>> s[0] = null;
 ** Null!! 

>>> Array a = ["naruto"];
>>> a[0] = null;
>>> a[0]
null
}}}

=== バイト配列 byte}{¥tt []}}

Konohaの整数型は、64ビット長のInt}型に単一化されているため、バイト(8ビット整数)を表す型はない。多少、メモリが無駄かも知れないが、int} でバイトを表すことになります。しかし、バイト列（バイナリデータ）となると、int}{¥tt []}を使うのは、多少の無駄では済まない。そこで、バイト列を扱う専用のクラスとして、Bytes}クラスが用意されています。byte}{¥tt []} は、ごたぶんに漏れず、Bytes}の別名です。

{{{
byte[] buf = new byte[4096];
}}}

バイト配列 int}{¥tt []} は、配列とほぼ同じ性質を持つ。本章で取り上げるメソッドや演算子をほぼそのまま利用することができます。バイト列を扱うときの特有な性質のみ、「第¥ref{bytearray}節 バイト配列」で取り上げる。

¥begin{comment}
=== 共変性** }

共変性(covariance)は、もともとはカテゴリー理論の用語に由来するらしいが、オブジェクト指向プログラミングにおけるクラス継承の説明に用いられます。

{{{

byte[] buf = new byte[4096];
}}}

% covariance と contravariance という言葉は、 元々は圏論（category theory）という数学の分野の用語で、 それぞれ共変性・反変性と訳します。

¥end{comment}

== 配列の生成}

配列は、配列リテラルでデータとして要素を列挙する方法と、プログラム中からnew}演算子を用いて生成する方法の2種類で生成することができます。

=== 配列リテラル}

配列リテラルは、Python や JavaScript などで採用されているデータ値を列挙し、四角括弧[ , , ]|で囲む記法を採用しています。C/C++やJavaの配列リテラルとは異なるが、こちらの方が JSON (JavaScript Object Notation)としてWeb上のデータ交換にも利用されています。

{{{
[1, 2, 3]                     // 1, 2, 3の配列
}}}

配列リテラルの要素は、Konoha がサポートするリテラルであれば含めることができます。ただし、変数や式を含めることは、セキュリティ上の観点から制限されています。

{{{
[
	"naruto",
	[1, 2, 3, 4],
]
}}}


=== 配列リテラルと型推論}

Konoha における重要な特徴は、リストの要素から配列リテラルの型が推論される点です。ただし、配列リテラルの型推論リールは、いたって単純です。まず、最初の要素の型 $T$を配列型 $T[]$の候補として、残りの要素がすべて $T$か、そのサブタイプであるとき、T[]|と推論する。そうでないときは、Array}クラスとなります。 

{{{
[]                            // 空の Array
[1,2,3]                       // Int[] の配列
["Naruto", "Sakura"]          // String[]の配列
["Naruto", 9]                 // Array
}}}

=== Array} コンストラクタ}

Array} クラスは、空のArray}オブジェクトを生成するコンストラクタをサポートしています。空の配列とは、大きさが0の配列です。空の配列に意味があるのかと思われるかもしれないが、KonohaのArray}は、可変長配列であり、後述する add()|メソッドによって要素を追加することができます。


{{{
>>> a = new Array();          // 空のArrayを生成
>>> |a|                       // サイズは？
0
>>> a.add(1)                  // 追加
>>> a
[1]
}}}

可変長配列は、許容量を超えると、再度メモリーアロケーションを行いながら、配列の大きさを成長させています。ある程度、配列が成長する大きさがわかっている許容量の初期値を設定することもできます。

{{{
>>> a = new Array(100);        // 初期許容量
>>> a
[]
}}}

=== T}{¥tt []}コンストラクタ}

T}{¥tt []}スタイルの配列は、Java と同様に、配列の大きさをあらかじめ与えて、配列を生成することができます。

{{{
>>> ss = new String[4];        // 要素数4個の配列String[]
>>> ss
["", "", "", ""]
>>> |ss|
4
}}}

このとき、生成された配列の要素は、要素型のデフォルト値(default(C)|)で満たされます。(Javaと異なり、null ではない。) デフォルト値が不要な場合は、要素数を0にして空の配列を生成することもできます。

{{{
>>> ss = new String[0];        // 空のString[]
>>> ss
[]
}}}

=== 配列リテラルとコンストラクタ}

配列は、整数や文字列と異なり、変更可能なオブジェクトです。そのため、配列リテラルをコンパイル時に定数プールで共有すると、変更されたときリテラルと要素の内容の間で一貫性が保証できなくなります。Konoha では、配列リテラルをコンパイル時にオブジェクト化せず、new}演算子によるコンストラクタ式に変換してコンパイルしています。

{{{
>>> int[] genArray123() {
...    return [1, 2, 3];
... }
>>> a = getArray123()          // 配列を生成
>>> a.reset()                  // 変更しても
>>> getArray123()              // もうひとつ生成
[1, 2, 3]
}}}

もし配列リテラルで定義した配列を共有したい場合は、先に定数（もしくはスクリプト変数）に格納しておく方法があります。（こちらの方が毎回、配列を生成しない分、高速になります。）ただし、共有されている配列オブジェクトを変更した場合、その変更も共有されるため、注意が必要となります。

{{{
>>> LIST123 = [1, 2, 3];       // 定数（ここで生成）
>>> int[] genArray123() {
...    return LIST123;
... }
>>> a = getArray123()          
>>> a.reset()                  // 変更すると
>>> getArray123()              // 変更が共有される
[]
}}}

注意： Array}クラスは、toImmutable()|メソッドによって、変更不可能な属性を与えることができます。ただし、この機能は、配列の型システムの見直しによって変更される可能性があります。

== 配列と演算子}

Konoha は、C/C++ 由来のインデックスによる配列へのアクセスからPython風のシーケンス演算子、スライシング演算子をサポートしています。

=== シーケンス演算子}

配列は、0個以上の要素が並んだ典型的なシーケンスです。Konohaでは、シーケンス s は、¥verb#|s|# 演算子を用いることで、その長さを得ることができます。配列の場合は、要素の数です。

{{{
>>> a = [0, 1, 2, 3]
>>> |a|
4
}}}

配列a|のインデックスは、C/C++, Java言語と同様に 0 から始まり、¥verb#|a| - 1# です。その範囲を超えると、OutOfIndex!!|例外が通知されます。

{{{
>>> a = [0, 1, 2, 3]
>>> a[0]
0
>>> a[|a|-1]
3
>>> a[4]
 ** OutOfIndex!!
}}}

配列は、基本的に変更可能です。正しいインデックスを指定すれば配列の値を変更できます。

{{{
>>> a = [0, 1, 2, 3]
>>> a[1] = 10                    // a[1]を変更
>>> a
[0, 10, 2, 3]
}}}

注意：初期のKonohaでは、python 風に最後尾からインデックスを数える $-n$ 表記が利用できた。このインデックスは便利であったが、C/C++, Java などの既存の配列処理との互換性や最適化処理の困難さを理由に廃止となった。

=== スライシング}

配列a|から部分配列を取り出すときは、スライス演算子a[m..n]|を用いることができます。$m$と$n$は、省略可能で、省略した場合は、それぞれ0と最後の添字(¥verb#|a|-1#)と解釈されます。

{{{
>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> a[2..]                       // a[2]から
[2, 3, 4, 5, 6, 7, 8]
>>> a[2..6]                      // a[2]からa[6]まで
[2, 3, 4, 5, 6]
>>> a[..<6]                      // a[2]からa[5]まで
[2, 3, 4, 5]
>>> a[2..+6]                     // a[2]から6個
[2, 3, 4, 5, 6, 7]
>>> a[..6]                       // a[6]まで
[0, 1, 2, 3, 4, 5, 6]
>>> a[..<6]                      // a[6]まで（含まない)
[0, 1, 2, 3, 4, 5]
>>> a[..+6]                      // 最初の6個
[0, 1, 2, 3, 4, 5, 6]
}}}

=== 要素の判定 {¥tt in?}}

配列では、in?|演算子を用いることで、配列中に与えられた要素が含まれているかどうか判定することができます。

{{{
>>> a = [1, 2, 4]
>>> 2 in? a                      // 含まれるか？
true
>>> 0 in? a                      
false
}}}

注意：Array}クラスのin?|は、単純な線形探索であるため、配列が大きくなるにつれ効率は悪くなります。実行性能が気になる場所では、HashSet} を代わりに用いた方がよい。

=== 集合演算**（調査中）}

配列は、シーケンスなので文字列と同様に、+|演算子によって連結したり、-|演算子によって要素の差分をとることができます。

{{{
>>> a = [1, 2, 3, 5]
>>> b = [2, 4]
>>> a + b                    // 連結
[1, 3, 5, 2, 4]
>>> a - b                    // 差分
[1, 3, 5]
}}}

Konoha では、配列に対し、集合として積(intersection)や和(union)の演算も定義しています。ただし、これらの演算子では、配列を集合として扱うため、順序を無視し、また重複する要素も自動的に除去されます。

{{{
>>> a = [1, 2, 3, 5]
>>> b = [2, 4]
>>> a & b                    // 集合積
[2]
>>> a | b                    // 集合和
[1, 2, 3, 4, 5]
}}}

== 多次元配列}

Konohaの配列は、基本的に1次元配列です。n 次元配列を使うというのは、単純に、C言語同様に、適切に次元を計算してからインデックス操作を行えばよい。例えば、それぞれの次元の大きさがX, Y, Z の3次元配列を使いたい場合は、次のようにインデックス(index|)を計算できます。

{{{
int[] a = new int[X * Y * Z];
index = x + X * y + (X * Y) * z;
a[index]
}}}

当初、多次元配列に関しては、これ以上の関心がなかった。それは、Konoha言語の開発を含め、過去のプログラミング経験から多次元配列がなくて困ったことはほとんどなかったからです。しかし、これも「クラスルーム」から来た要求であるが、プログラミング練習課題には、オセロやら五目並べやらと、2次元配列を使うものが多い。学生たちから「2次元配列は使えないのですか？」と質問がくる度に、シンタックスシュガーでさっさと対応すべきではないか？、ということになった。

そういうわけで、Konohaの多次元配列は、型としては1次元配列のときと同じArray}クラスです。ただし、コンストラクタで２次元もしくは３次元の大きさを設定すると、その次元情報はメタデータとして記録されます。このメタ情報を用いてインデックスをを再計算しています。確かに、上記のプログラムよりは、すっきりする。

{{{
int[] a = new int[X, Y, Z];
a[x, y, z]
}}}

次は、2次元配列の利用例です。クラスルームで使う程度であれば、ふつうの2次元配列として利用することができます。

{{{
>>> a = new Int[8, 8];         // 2次元配列
>>> a[1, 7] = 1
>>> a[1, 7]
1
>>> a[8, 1]                    // 次元単位でチェック
 ** OutOfIndex!!
}}}

多次元配列は、1次元配列なので、1次元配列として操作することもできます。多次元配列としての型安全性は備えていない。

{{{
>>> a = new Int[8, 8];         // 2次元配列
>>> typeof(a)
Int[]
>>> |a|                        // 大きさは、1次元
64
>>> a.add(100)                 // 追加もできる
>>> |a|
65
>>> a[64]                      // 1次元配列の操作も可
100
}}}

%注意：Konoha の Array}は、次元をメタ情報として管理しているため、次元数に上限が生じる。最もよく使うと考えられる2次元、もしくは3次元配列のみサポートされています。4次元配列が必要なアプリケーションを書いておられる方は、是非、連絡して欲しい。

== 配列とメソッド}

Konohaは、JavaのCollection フレームワークの標準的なメソッドをベースにしてArray}関係のメソッドを定義しています。

=== リスト: add(), insert(), remove()}

Konohaの配列は、全て可変長であり、リストのように要素数のわからないデータを実行時に必要に応じて伸縮させながら利用できます。

メソッドadd(v)|は、最もよく使われるメソッドです。配列の最後尾に新しい要素v|を追加する。演算子 <<|と同じ働きをする。

{{{
>>> a = [0, 1, 2]
>>> a.add(100)　　　　　　　　　　// 追加
>>> a
[0, 1, 2, 100]
>>> a.add(30000)                  // 追加
>>> a
[0, 1, 2, 100, 300000]
}}}

メソッドinsert(n, v)|は、n|番目に要素v|を挿入するときに利用し、メソッドremove(n)|は、n|番目からを取り除くとき利用する。どちらの場合は、配列の大きさは、それぞれ増減する。

{{{
>>> a = [0, 1, 2]
>>> a.insert(1, 100)　　　　　　　// 挿入
>>> a
[0, 100, 1, 2]
>>> a.remove(2)                   // 削除
>>> a
[0, 100, 2]
}}}

Konohaの配列は、リストのように利用できるが、双方向リンクリスト構造ではないため、insert(), remove()|ともに配列要素をコピーするだけのコストがかかる。add()|は、十分に高速に要素を追加することができます。

=== キューとスタック: first(), pop()}

Konohaの配列は、キュー(FIFO)やスタック(FILO)として利用することができます。

次は、配列のキューとしての操作例あります。キューに追加するときは、配列と同じく、add()|を用います。first()|は最初の要素を取り出すメソッドです。キューが空であれば、ブロックされるか、もしくはThread!!}例外が投げられます。（先に、¥verb#|queue|#でキューの大きさを検査する必要があります。)

{{{
>>> queue = []
>>> queue.add(1)            // 最後尾に追加
>>> queue << 2 << 3         // 更に追加
>>> queue
[1, 2, 3]
>>> queue.first()           // キューから取り出す
1
>>> queue
[2, 3]
}}}

次は、スタックとしての操作例です。スタックに要素を追加するのは同じく add()|を用います。pop()|は最後に追加した要素を取り出すメソッドです。スタックが空の場合は、pop()|は、StackUnderFlow!!}例外を投げる。（注意：add()とpop()が非対称なコードはバグなので、スタックサイズを検査する必要はない。）

{{{
>>> stack = []
>>> stack.add(1)            // 最後尾に追加
>>> stack << 2 << 3         // 更に追加
>>> stack
[1, 2, 3]
>>> stack.pop()             // スタックから取り出す
3
>>> stack
[1, 2]
}}}

注意：配列は、スタックとして利用するとき、配列の大きさに関わらず、十分に高速です。しかし、キュー操作の場合は、first()|のとき配列要素のコピーが発生するため、配列の大きさに応じてコストがかかる。

=== 整列：sort()}

Konohaは、高速なソートアルゴリズム(qsort相当)によって配列の要素の並びかえることができます。大小の比較は、オブジェクト間の標準的な比較方法、つまり <| 演算子によって行われます。

{{{
>>> a = [3, 2, 1, 5, 4]
>>> a.sort()        　　　　　　　// ソート
>>> a
[1, 2, 3, 4, 5]
}}}

sort()|は、いわゆる昇順ソート(assending sort)です。降順ソート(decending sort)のためのメソッドは用意されていない。ただし、sort()|とreverse()|を組み合わせると、降順になります。

{{{
>>> a
[1, 2, 3, 4, 5]
>>> a.reverse()
[5, 4, 3, 2, 1]
}}}

¥subsubsection{比較方法の入れ替え**}

sort()| メソッドは、標準Cライブラリのソートアルゴリズムと同様に、配列の要素の比較方法を切り替えることができます。Konohaでは、関数ポインタの代わりに、クロージャを用います。

次は、文字列の比較をケースインセンシブなバージョンに変更した例です。スクリプト関数cmpr|は、qsortライブラリの比較関数と同様に、比較した結果が小さければ負の数(-1), 等しければ0、大きければ正の数(1)を返す。それをdelegate()|でクロージャ化し、sort()|メソッドに渡しています。

{{{
>>> int cmpr(String a, String b) {
...    return a.compareTo:IgnoreCase(b);
... }
>>> s = ["SASUKE", "sakura", "naruto"]
>>> s.sort(delegate(cmpr));    // クロージャ化
>>> s
["naruto", "sakura", "SASUKE"]
}}}

sort()|メソッドが受け付けるクロージャの型は、Array}<|T}>|に対して、int(T, T)}です。クロージャに関しては、「第 ¥ref{closure} 章 クロージャ」を参考にして欲しい。

=== ランダム化：shuffle()}

ゲーム開発、負荷分散、セキュリティ対策など、様々な場面で配列の要素をランダム化する機会は多い。shuffle()|は、配列の要素をランダムに並べるメソッドです。（乱数は、Int.random() 同様にMersenne Twisterを利用しています。）

{{{
>>> a = [1, 2, 3, 4, 5]
>>> a.shuffle()
[3, 2, 1, 5, 4]
}}}

=== サーチ: indexOf(), lastIndexOf(), binarySearch()}

サーチは、配列中から指定された要素を探すことです。配列は、indexOf()|は、先頭から探して最初に見つかったインデックスを返す。lastIndexOf()|は、逆に最後尾から検索して最初に見つかった箇所のインデックスを返す。ともに発見できなかった場合は、-1を返す。

{{{
>>> a = [1, 2, 3, 2, 1]
>>> a.indexOf(2)    　　　　　　　// 先頭から検索
1
>>> a.lastIndexOf(2)    　　　　　// 後尾から検索
3
>>> a.indexOf(0)                  // 見つからない
-1
}}}

indexOf()|とlastIndexOf()|は、どのような配列に対しても検索が可能です。しかし、単純に順番に検索するため、検索時間は配列の大きさに比例し、効率はあまりよいといえない。もし配列がsort()|で整列された状態であるときは、binarySearch()|を用いると、バイナリーサーチアルゴリズムにより効率よく検索することができます。

{{{
>>> a = [1, 3, 2, 4, 0]
>>> a.sort()
>>> a
[0, 1, 2, 3, 4]
>>> a.binarySearch(3)             // バイナリサーチ
3
>>> a.binarySearch(5)             // 見つからない
-1
}}}

=== 文字列への連結: format()*}

format(fmt, delim)|メソッドは、配列の各要素に対し、与えられたフォーマッタfmtを適用し、更にdelimで連結してフォーマットする機能です。

{{{
>>> a = ["naruto", 9]
>>> a.format("%s", ",")
"naruto,9"

>>> a.format("%k", EOL)
"naruto"
9
>>>
}}}

== バイト配列: byte}{¥tt []}}
¥label{bytearray}

バイト配列は、バイナリデータを扱うための専用の配列であり、ヒープ上のメモリを確保し、それをダイレクトに扱うことができます。バイト配列の大きさは、バイト数です。

{{{
>>> buf = new byte[4096];
>>> typeof(buf)
Bytes
>>> |buf|
4096
}}}

各要素のとりうる値は、0 〜 255 (0xff)であり、この値域に当てはまらない整数は丸め込まれる。(型エラーとならない。）

{{{
>>> buf[0]
0
>>> buf[0] = -1
255
}}}

sort()|やshuffle()|など、バイナリ操作に関係ないメソッドをサポートしていないが、それ以外は配列と同じように操作することができます。以下は、バイト配列に特徴的な機能のみ紹介する。

=== バイトコピー: Bytes.memcpy()*}

クラス関数 Bytes.memcpy(dst, s1, src, s2, n)|は、memcpy()のバイト配列版です。バイト配列 dst の先頭からs1バイト目へ バイト配列 srcのs2バイト目から、nバイトコピーする。名前が示すとおり、C標準ライブラリが提供する memcpy を利用しているため、スクリプト上で配列操作するより格段に高速です。

{{{
>>> Bytes.memcpy(dst, 0, src, 0, 256)
}}}

=== ストリームへの変換*}

バイト配列は、InputStream}, OutputStream}にへラップして操作することができます。(これらは、JavaのByteArrayInputStream, ByteArrayOutputStreamに相当する。)

ba.wrapInputStream(offset, length)|は、バイト配列 ba の offsetバイト目からlength分に相当する部分を読むInputStream}をつくる。offsetとlengthはそれぞれ省略すると、最初から最後まで、と解釈されます。

{{{
>>> ba = Bytes.readFile('coredump');
>>> bin = ba.wrapInputStream();     // (InputStream)ba
>>> data = bin.readData();
}}}

ba.wrapOutputStream(offset)|は、バイト配列 ba の offsetバイト目から追加で書き込むOutputStream}をつくる。offsetは省略すると、「最初から」と解釈されます。バイト配列も可変長であるため、メモリが許す限り追加することができます。（上限制限は必要か？）特に、OutputStream} ストリームやフォーマッタの一部として利用できるため、便利です。

{{{
>>> ba = new byte[4096];            // 初期の大きさ
>>> bout = ba.wrapOutputStream(0);  // (OutputStream)ba
>>> bout.println("hello, world");
>>> bout.close()

>>> %dump(ba)                       // ba

}}}

InputStream}やOutputStream}の詳しい情報は、「第 ¥ref{stream} 章 ストリーム」で紹介する。こちらもあわせて、参照してほしい。

%=== バイト配列: {¥tt byte[]}}

¥begin{comment}

¥end{comment}
