差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
tutorial:nim:containers [2024/03/11 21:36] – [スライス] freemikan | tutorial:nim:containers [2025/05/20 11:21] (現在) – 削除 freemikan | ||
---|---|---|---|
行 1: | 行 1: | ||
- | ====== コンテナ ====== | ||
- | |||
- | 複数の値を保持することの出来るデータ型をコンテナと呼ぶことにします。コンテナの種類はいくつかあります。 | ||
- | |||
- | ====== 配列 ====== | ||
- | |||
- | 配列は同種の型の値を保持できる固定長のコンテナです。固定長であることは、作成した後にそのサイズを変更できないことを意味します。また、サイズはコンパイル時定数でなければなりません。 | ||
- | |||
- | 配列型の変数の宣言は、型を明示的に書くと次のようになります。 | ||
- | |||
- | < | ||
- | let xs: array[3, int] = [1, 2, 3] | ||
- | echo xs #=> [1, 2, 3] | ||
- | </ | ||
- | |||
- | 通常の変数の場合と同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。 | ||
- | |||
- | < | ||
- | let a = [1, 2, 3] | ||
- | echo a #=> [1, 2, 3] | ||
- | </ | ||
- | |||
- | '' | ||
- | |||
- | < | ||
- | var a: array[3, int] | ||
- | echo a #=> [0, 0, 0] | ||
- | </ | ||
- | |||
- | ゼロ値以外で初期化したい場合の特別な方法はありません。一旦変数を作成してから、for文で設定するのが妥当な方法です。 | ||
- | |||
- | < | ||
- | var a: array[3, int] | ||
- | for x in a.mitems: | ||
- | x = 99 | ||
- | echo a #=> [99, 99, 99] | ||
- | </ | ||
- | |||
- | '' | ||
- | |||
- | 配列の宣言には'' | ||
- | |||
- | < | ||
- | var a: array[0..2, int] | ||
- | echo a #=> [0, 0, 0] | ||
- | </ | ||
- | |||
- | これはインデックスが0から2の、すなわち、サイズが3の配列を作成します。 | ||
- | |||
- | |||
- | |||
- | |||
- | ====== シーケンス ====== | ||
- | |||
- | シーケンスは、配列と同様、同じ種類の型の値を保持できる可変長のコンテナです。可変長であることは、作成した後に新たな要素を追加したり削除したり出来ることを意味します。 | ||
- | |||
- | シーケンスの変数の宣言は、型を明示的に書くと次のようになります。 | ||
- | |||
- | < | ||
- | let xs: seq[int] = @[1, 2, 3] | ||
- | echo xs #=> @[1, 2, 3] | ||
- | </ | ||
- | |||
- | 型の指定で'' | ||
- | |||
- | < | ||
- | let xs = @[1, 2, 3] | ||
- | echo xs #=> @[1, 2, 3] | ||
- | </ | ||
- | |||
- | 上の2つの例ではシーケンスの変数の宣言に'' | ||
- | |||
- | < | ||
- | var xs: seq[int] = @[1, 2, 3] | ||
- | |||
- | xs.add(10) | ||
- | echo xs #=> @[1, 2, 3, 10] | ||
- | |||
- | xs.delete(0) | ||
- | echo xs #=> @[2, 3, 10] | ||
- | </ | ||
- | |||
- | deleteプロシージャの引数に与えるのは、削除したい要素がシーケンスの何番目であるかを示すインデックスです。シーケンスのインデックスは他の多くの言語と同様に0始まりです。 | ||
- | |||
- | シーケンスを作成する別の方法は、newSeqプロシージャを使うことです。 | ||
- | |||
- | < | ||
- | var xs = newSeq[int]() | ||
- | xs.add(1) | ||
- | xs.add(2) | ||
- | xs.add(3) | ||
- | echo xs #=> @[1, 2, 3] | ||
- | </ | ||
- | |||
- | シーケンスに関連するプロシージャは他にもいくつかあります。[[https:// | ||
- | |||
- | ====== インデックス ====== | ||
- | |||
- | 配列とシーケンスの要素には'' | ||
- | |||
- | < | ||
- | let xs = [1, 2, 3, 4, 5] | ||
- | let x0 = xs[0] | ||
- | echo x0 #=> 1 | ||
- | let x1 = xs[1] | ||
- | echo x0 #=> 2 | ||
- | </ | ||
- | |||
- | インデックスは0始まりです。範囲外アクセスは実行時にチェックされエラーとなります。 | ||
- | |||
- | < | ||
- | let xs = [1, 2, 3, 4, 5] | ||
- | let x100 = xs[100] | ||
- | </ | ||
- | |||
- | このプログラムを実行すると次のエラーが出力されます。 | ||
- | |||
- | Error: index 100 not in 0 .. 4 | ||
- | |||
- | 配列は宣言でインデックスの範囲を指定できるので、そうした場合は、取り得るインデックスの範囲はその範囲に制限されます。 | ||
- | |||
- | < | ||
- | let xs: array[2..6, int]= [1, 2, 3, 4, 5] | ||
- | let x0 = xs[0] # 範囲外アクセス! | ||
- | </ | ||
- | |||
- | このプログラムを実行すると次のエラーが出力されます。 | ||
- | |||
- | Error: index 0 not in 2 .. 6 | ||
- | |||
- | '' | ||
- | < | ||
- | let xs = [1, 2, 3, 4, 5] | ||
- | let x4 = xs[^1] | ||
- | echo x4 #=> 5 | ||
- | let x3 = xs[^2] | ||
- | echo x3 #=> 4 | ||
- | </ | ||
- | |||
- | <WRAP important> | ||
- | 後方からのインデックスのルールに従えば、xsに対する'' | ||
- | </ | ||
- | |||
- | 配列やシーケンスを'' | ||
- | |||
- | < | ||
- | var xs =[1, 2, 3, 4, 5] | ||
- | xs[0] = 100 | ||
- | xs[1] = 200 | ||
- | xs[^2] = 400 | ||
- | echo xs #=> [100, 200, 3, 400, 5] | ||
- | </ | ||
- | |||
- | インデックスによるアクセスは'' | ||
- | |||
- | |||
- | ====== スライス ====== | ||
- | |||
- | '' | ||
- | |||
- | < | ||
- | let xs = [1, 2, 3, 4, 5] | ||
- | let s = xs[1..3] | ||
- | echo s #=> @[2, 3, 4] | ||
- | </ | ||
- | |||
- | 出力に'' | ||
- | |||
- | < | ||
- | let xs = [1, 2, 3, 4, 5] | ||
- | var s = xs[1..3] | ||
- | s[0] = 200 | ||
- | s.add(999) | ||
- | echo s # | ||
- | echo xs #=> [1, 2, 3, 4, 5] | ||
- | </ | ||
- | |||
- | '' | ||
- | |||
- | < | ||
- | var xs = [1, 2, 3, 4, 5] | ||
- | xs[1..3] = [200, 300, 400] # @[200, 300, 400]としても同じ結果になる | ||
- | echo xs #=> [1, 200, 300, 400, 5] | ||
- | </ | ||
- | |||
- | スライスへの代入の挙動には、配列とシーケンスで重要な違いがあります。配列の場合は'' | ||
- | |||
- | < | ||
- | var xs = [1, 2, 3, 4, 5] | ||
- | xs[1..3] = [200, 300, 400, 500] # 要素数が異なる! | ||
- | </ | ||
- | |||
- | このプログラムを実行すると、次のエラーが出力されます。 | ||
- | |||
- | Error: unhandled exception: different lengths for slice assignment [RangeDefect] | ||
- | |||
- | シーケンスの場合は問題ありません。スライスの範囲が右辺の要素数に合うように置き換えられます。 | ||
- | |||
- | < | ||
- | var xs = @[1, 2, 3, 4, 5] | ||
- | xs[1..3] = [200, 300, 400, 500] | ||
- | echo xs # | ||
- | xs[1..3] = [999] | ||
- | echo xs # | ||
- | </ | ||
- | |||
- | スライスは'' | ||
- | ====== タプル ====== | ||
- | |||
- | タプルは異なる種類の型の値を保持できる固定長のコンテナです。タプルの変数は次のように宣言することが出来ます。 | ||
- | |||
- | < | ||
- | let one: (int, float, string) = (1, 1.0, " | ||
- | echo one #=> (1, 1.0, " | ||
- | </ | ||
- | |||
- | これまでと同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。 | ||
- | |||
- | < | ||
- | let one = (1, 1.0, " | ||
- | echo one #=> (1, 1.0, " | ||
- | </ | ||
- | |||
- | タプルの各要素にアクセスするには'' | ||
- | |||
- | < | ||
- | let one = (1, 1.0, " | ||
- | let i = one[0] | ||
- | let f = one[1] | ||
- | let s = one[2] | ||
- | echo i #=> 1 | ||
- | echo f #=> 1.0 | ||
- | echo s #=> one | ||
- | </ | ||
- | |||
- | タプルを'' | ||
- | |||
- | タプルは要素を指すインデックスに名前を付けることが出来ます。これをフィールド名と呼ぶことにします。 | ||
- | |||
- | < | ||
- | let one: tuple[ival: int, fval: float, name: string] = (ival: 1, fval: 1.0, name: " | ||
- | echo one #=> (ival: 1, fval: 1.0, name: " | ||
- | </ | ||
- | |||
- | やはり、型推論によって明示的な型の指定は省略できます。 | ||
- | |||
- | < | ||
- | let one = (ival: 1, fval: 1.0, name: " | ||
- | echo one #=> (ival: 1, fval: 1.0, name: " | ||
- | </ | ||
- | |||
- | 各フィールドにアクセスするには'' | ||
- | |||
- | < | ||
- | let one = (ival: 1, fval: 1.0, name: " | ||
- | let i = one.ival | ||
- | let f = one.fval | ||
- | let s = one.name | ||
- | echo i #=> 1 | ||
- | echo f #=> 1.0 | ||
- | echo s #=> one | ||
- | </ | ||
- | |||
- | タプルを'' | ||
- | |||
- | ====== その他のコンテナ ====== | ||
- | |||
- | これまで見てきたコンテナは、順序付けられたコンテナでした。その他のコンテナについても少しだけ触れておきます。 | ||
- | |||
- | キーと値のペアを格納するコンテナはテーブル(table)という名前で提供されています((他の言語でマップ(map)や辞書(dictionary)と呼ばれるものです))。テーブルを利用するには、'' | ||
- | |||
- | |||
- | 数学の集合を表すsetが組み込みでサポートされていますが、他の多くの言語のsetとは違い、テーブルの値を持たないバージョンのようなものではなくもっと限定的なものです。他の言語のsetような用途の広いsetが必要ならば、'' | ||
- | |||