ユーザ用ツール

サイト用ツール


tutorial:nim:containers

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
tutorial:nim:containers [2024/03/11 21:36] – [スライス] freemikantutorial:nim:containers [2024/08/19 19:20] (現在) freemikan
行 3: 行 3:
 複数の値を保持することの出来るデータ型をコンテナと呼ぶことにします。コンテナの種類はいくつかあります。 複数の値を保持することの出来るデータ型をコンテナと呼ぶことにします。コンテナの種類はいくつかあります。
  
-====== 配列 ======+===== 配列 =====
  
 配列は同種の型の値を保持できる固定長のコンテナです。固定長であることは、作成した後にそのサイズを変更できないことを意味します。また、サイズはコンパイル時定数でなければなりません。 配列は同種の型の値を保持できる固定長のコンテナです。固定長であることは、作成した後にそのサイズを変更できないことを意味します。また、サイズはコンパイル時定数でなければなりません。
行 9: 行 9:
 配列型の変数の宣言は、型を明示的に書くと次のようになります。 配列型の変数の宣言は、型を明示的に書くと次のようになります。
  
-<codeprism lang=nim>+<file nim>
 let xs: array[3, int] = [1, 2, 3] let xs: array[3, int] = [1, 2, 3]
 echo xs    #=> [1, 2, 3] echo xs    #=> [1, 2, 3]
-</codeprism>+</file>
  
 通常の変数の場合と同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。 通常の変数の場合と同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。
  
-<codeprism lang=nim>+<file nim>
 let a = [1, 2, 3] let a = [1, 2, 3]
 echo a    #=> [1, 2, 3] echo a    #=> [1, 2, 3]
-</codeprism>+</file>
  
 ''let''で宣言する変数には初期値を与えなければなりません。''var''で宣言する場合、初期値を省略するとゼロ初期化されます。 ''let''で宣言する変数には初期値を与えなければなりません。''var''で宣言する場合、初期値を省略するとゼロ初期化されます。
  
-<codeprism lang=nim>+<file nim>
 var a: array[3, int] var a: array[3, int]
 echo a    #=> [0, 0, 0] echo a    #=> [0, 0, 0]
-</codeprism>+</file>
  
 ゼロ値以外で初期化したい場合の特別な方法はありません。一旦変数を作成してから、for文で設定するのが妥当な方法です。 ゼロ値以外で初期化したい場合の特別な方法はありません。一旦変数を作成してから、for文で設定するのが妥当な方法です。
  
-<codeprism lang=nim>+<file nim>
 var a: array[3, int] var a: array[3, int]
 for x in a.mitems: for x in a.mitems:
   x = 99   x = 99
 echo a    #=> [99, 99, 99] echo a    #=> [99, 99, 99]
-</codeprism>+</file>
  
 ''mitems''は要素を変更可能な状態で配列を走査します。 ''mitems''は要素を変更可能な状態で配列を走査します。
行 41: 行 41:
 配列の宣言には''array[<サイズ>, <要素の型>]''ではなく、''array[<インデックスの範囲>, <要素の型>]''とすることも出来ます。 配列の宣言には''array[<サイズ>, <要素の型>]''ではなく、''array[<インデックスの範囲>, <要素の型>]''とすることも出来ます。
  
-<codeprism lang=nim>+<file nim>
 var a: array[0..2, int] var a: array[0..2, int]
 echo a    #=> [0, 0, 0] echo a    #=> [0, 0, 0]
-</codeprism>+</file>
  
 これはインデックスが0から2の、すなわち、サイズが3の配列を作成します。 これはインデックスが0から2の、すなわち、サイズが3の配列を作成します。
行 51: 行 51:
  
  
-====== シーケンス ======+===== シーケンス =====
  
 シーケンスは、配列と同様、同じ種類の型の値を保持できる可変長のコンテナです。可変長であることは、作成した後に新たな要素を追加したり削除したり出来ることを意味します。 シーケンスは、配列と同様、同じ種類の型の値を保持できる可変長のコンテナです。可変長であることは、作成した後に新たな要素を追加したり削除したり出来ることを意味します。
行 57: 行 57:
 シーケンスの変数の宣言は、型を明示的に書くと次のようになります。 シーケンスの変数の宣言は、型を明示的に書くと次のようになります。
  
-<codeprism lang=nim>+<file nim>
 let xs: seq[int] = @[1, 2, 3] let xs: seq[int] = @[1, 2, 3]
 echo xs    #=> @[1, 2, 3] echo xs    #=> @[1, 2, 3]
-</codeprism>+</file>
  
 型の指定で''array''の代わりに''seq''としていることとサイズを指定しないことが配列の場合と異なります。また、初期値として与えるシーケンスのリテラルは''[<要素>]''の代わりに、''@[<要素>]''となることが配列の場合と異なります。 配列の場合と同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。  型の指定で''array''の代わりに''seq''としていることとサイズを指定しないことが配列の場合と異なります。また、初期値として与えるシーケンスのリテラルは''[<要素>]''の代わりに、''@[<要素>]''となることが配列の場合と異なります。 配列の場合と同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。 
  
-<codeprism lang=nim>+<file nim>
 let xs = @[1, 2, 3] let xs = @[1, 2, 3]
 echo xs    #=> @[1, 2, 3] echo xs    #=> @[1, 2, 3]
-</codeprism>+</file>
  
 上の2つの例ではシーケンスの変数の宣言に''let''を用いました。こうすると、シーケンスの内容を変更することが出来ないので意味がありません。ほとんどの場合、シーケンスは''var''にすることになるでしょう。''var''にすれば、addプロシージャやdeleteプロシージャで要素の追加や削除ができます。 上の2つの例ではシーケンスの変数の宣言に''let''を用いました。こうすると、シーケンスの内容を変更することが出来ないので意味がありません。ほとんどの場合、シーケンスは''var''にすることになるでしょう。''var''にすれば、addプロシージャやdeleteプロシージャで要素の追加や削除ができます。
  
-<codeprism lang=nim>+<file nim>
 var xs: seq[int] = @[1, 2, 3] var xs: seq[int] = @[1, 2, 3]
  
行 79: 行 79:
 xs.delete(0) xs.delete(0)
 echo xs    #=> @[2, 3, 10] echo xs    #=> @[2, 3, 10]
-</codeprism>+</file>
  
 deleteプロシージャの引数に与えるのは、削除したい要素がシーケンスの何番目であるかを示すインデックスです。シーケンスのインデックスは他の多くの言語と同様に0始まりです。 deleteプロシージャの引数に与えるのは、削除したい要素がシーケンスの何番目であるかを示すインデックスです。シーケンスのインデックスは他の多くの言語と同様に0始まりです。
行 85: 行 85:
 シーケンスを作成する別の方法は、newSeqプロシージャを使うことです。 シーケンスを作成する別の方法は、newSeqプロシージャを使うことです。
  
-<codeprism lang=nim>+<file nim>
 var xs = newSeq[int]() var xs = newSeq[int]()
 xs.add(1) xs.add(1)
行 91: 行 91:
 xs.add(3) xs.add(3)
 echo xs    #=> @[1, 2, 3] echo xs    #=> @[1, 2, 3]
-</codeprism>+</file>
  
 シーケンスに関連するプロシージャは他にもいくつかあります。[[https://nim-lang.org/docs/system.html#system-module-seqs|マニュアル]] シーケンスに関連するプロシージャは他にもいくつかあります。[[https://nim-lang.org/docs/system.html#system-module-seqs|マニュアル]]
  
-====== インデックス ======+===== インデックス =====
  
 配列とシーケンスの要素には''[]''とインデックスを使ってアクセスできます。 配列とシーケンスの要素には''[]''とインデックスを使ってアクセスできます。
  
-<codeprism lang=nim>+<file nim>
 let xs = [1, 2, 3, 4, 5] let xs = [1, 2, 3, 4, 5]
 let x0 = xs[0] let x0 = xs[0]
行 105: 行 105:
 let x1 = xs[1] let x1 = xs[1]
 echo x0    #=> 2 echo x0    #=> 2
-</codeprism>+</file>
  
 インデックスは0始まりです。範囲外アクセスは実行時にチェックされエラーとなります。 インデックスは0始まりです。範囲外アクセスは実行時にチェックされエラーとなります。
  
-<codeprism lang=nim>+<file nim>
 let xs = [1, 2, 3, 4, 5] let xs = [1, 2, 3, 4, 5]
 let x100 = xs[100]    # 範囲外アクセス! let x100 = xs[100]    # 範囲外アクセス!
-</codeprism>+</file>
  
 このプログラムを実行すると次のエラーが出力されます。 このプログラムを実行すると次のエラーが出力されます。
行 120: 行 120:
 配列は宣言でインデックスの範囲を指定できるので、そうした場合は、取り得るインデックスの範囲はその範囲に制限されます。 配列は宣言でインデックスの範囲を指定できるので、そうした場合は、取り得るインデックスの範囲はその範囲に制限されます。
  
-<codeprism lang=nim>+<file nim>
 let xs: array[2..6, int]= [1, 2, 3, 4, 5] let xs: array[2..6, int]= [1, 2, 3, 4, 5]
 let x0 = xs[0]    # 範囲外アクセス! let x0 = xs[0]    # 範囲外アクセス!
-</codeprism>+</file>
  
 このプログラムを実行すると次のエラーが出力されます。 このプログラムを実行すると次のエラーが出力されます。
行 130: 行 130:
  
 ''^n''で後方からインデックス出来ます。xsに対する''^1''は''len(xs) - 1''、''^2''は''len(xs)-2''となります。 ''^n''で後方からインデックス出来ます。xsに対する''^1''は''len(xs) - 1''、''^2''は''len(xs)-2''となります。
-<codeprism lang=nim>+<file nim>
 let xs = [1, 2, 3, 4, 5] let xs = [1, 2, 3, 4, 5]
 let x4 = xs[^1] let x4 = xs[^1]
行 136: 行 136:
 let x3 = xs[^2] let x3 = xs[^2]
 echo x3    #=> 4 echo x3    #=> 4
-</codeprism>+</file>
  
 <WRAP important> <WRAP important>
行 144: 行 144:
 配列やシーケンスを''let''ではなく''var''で宣言すれば、インデックスの位置の要素を変更することが出来ます。 配列やシーケンスを''let''ではなく''var''で宣言すれば、インデックスの位置の要素を変更することが出来ます。
  
-<codeprism lang=nim>+<file nim>
 var xs =[1, 2, 3, 4, 5] var xs =[1, 2, 3, 4, 5]
 xs[0] = 100 xs[0] = 100
行 150: 行 150:
 xs[^2] = 400 xs[^2] = 400
 echo xs    #=> [100, 200, 3, 400, 5] echo xs    #=> [100, 200, 3, 400, 5]
-</codeprism>+</file>
  
 インデックスによるアクセスは''string''でも同じように使えます。 インデックスによるアクセスは''string''でも同じように使えます。
  
  
-====== スライス ======+===== スライス =====
  
 ''[]''で指定するインデックスを範囲指定に置き換えると、スライスを取得することが出来ます。 ''[]''で指定するインデックスを範囲指定に置き換えると、スライスを取得することが出来ます。
  
-<codeprism lang=nim>+<file nim>
 let xs = [1, 2, 3, 4, 5] let xs = [1, 2, 3, 4, 5]
 let s = xs[1..3] let s = xs[1..3]
 echo s    #=> @[2, 3, 4] echo s    #=> @[2, 3, 4]
-</codeprism>+</file>
  
 出力に''@''が付加されていることから、スライスはシーケンスであることが見て取れます。スライスを''let''ではなく''var''とすることで、変更を加えることが出来ます。この場合、''s''に変更を加えても元となった配列に影響は及びません。 出力に''@''が付加されていることから、スライスはシーケンスであることが見て取れます。スライスを''let''ではなく''var''とすることで、変更を加えることが出来ます。この場合、''s''に変更を加えても元となった配列に影響は及びません。
  
-<codeprism lang=nim>+<file nim>
 let xs = [1, 2, 3, 4, 5] let xs = [1, 2, 3, 4, 5]
 var s = xs[1..3] var s = xs[1..3]
行 174: 行 174:
 echo s     #=> @[200, 3, 4, 999] echo s     #=> @[200, 3, 4, 999]
 echo xs    #=> [1, 2, 3, 4, 5] echo xs    #=> [1, 2, 3, 4, 5]
-</codeprism>+</file>
  
 ''s''に対する変更が''xs''に反映されていないことが分かります。しかし、取得したスライスを変数に格納することなく、直接に値を代入することで、元になった配列の複数要素へ変更を加えることが出来ます。 ''s''に対する変更が''xs''に反映されていないことが分かります。しかし、取得したスライスを変数に格納することなく、直接に値を代入することで、元になった配列の複数要素へ変更を加えることが出来ます。
  
-<codeprism lang=nim>+<file nim>
 var xs = [1, 2, 3, 4, 5] var xs = [1, 2, 3, 4, 5]
 xs[1..3] = [200, 300, 400] # @[200, 300, 400]としても同じ結果になる xs[1..3] = [200, 300, 400] # @[200, 300, 400]としても同じ結果になる
 echo xs    #=> [1, 200, 300, 400, 5] echo xs    #=> [1, 200, 300, 400, 5]
-</codeprism>+</file>
  
 スライスへの代入の挙動には、配列とシーケンスで重要な違いがあります。配列の場合は''xs[1..3]''の要素数が3つなので、右辺の要素数もちょうど3つでなければなりません。もしそうでなければ、実行時エラーとなります。 スライスへの代入の挙動には、配列とシーケンスで重要な違いがあります。配列の場合は''xs[1..3]''の要素数が3つなので、右辺の要素数もちょうど3つでなければなりません。もしそうでなければ、実行時エラーとなります。
  
-<codeprism lang=nim>+<file nim>
 var xs = [1, 2, 3, 4, 5] var xs = [1, 2, 3, 4, 5]
 xs[1..3] = [200, 300, 400, 500] # 要素数が異なる! xs[1..3] = [200, 300, 400, 500] # 要素数が異なる!
-</codeprism>+</file>
  
 このプログラムを実行すると、次のエラーが出力されます。 このプログラムを実行すると、次のエラーが出力されます。
行 197: 行 197:
 シーケンスの場合は問題ありません。スライスの範囲が右辺の要素数に合うように置き換えられます。 シーケンスの場合は問題ありません。スライスの範囲が右辺の要素数に合うように置き換えられます。
  
-<codeprism lang=nim>+<file nim>
 var xs = @[1, 2, 3, 4, 5] var xs = @[1, 2, 3, 4, 5]
 xs[1..3] = [200, 300, 400, 500] xs[1..3] = [200, 300, 400, 500]
行 203: 行 203:
 xs[1..3] = [999] xs[1..3] = [999]
 echo xs     #=> @[1, 999, 500, 5] echo xs     #=> @[1, 999, 500, 5]
-</codeprism>+</file>
  
 スライスは''string''にも使えます。変更を加える場合は、シーケンスと同じように、スライスの範囲が右辺の要素数に合うように置き換えられます。 スライスは''string''にも使えます。変更を加える場合は、シーケンスと同じように、スライスの範囲が右辺の要素数に合うように置き換えられます。
-====== タプル ======+ 
 +===== タプル =====
  
 タプルは異なる種類の型の値を保持できる固定長のコンテナです。タプルの変数は次のように宣言することが出来ます。 タプルは異なる種類の型の値を保持できる固定長のコンテナです。タプルの変数は次のように宣言することが出来ます。
  
-<codeprism lang=nim>+<file nim>
 let one: (int, float, string) = (1, 1.0, "one") let one: (int, float, string) = (1, 1.0, "one")
 echo one    #=> (1, 1.0, "one") echo one    #=> (1, 1.0, "one")
-</codeprism>+</file>
  
 これまでと同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。  これまでと同様に型推論が機能するので、明示的な型の指定は省略することが出来ます。 
  
-<codeprism lang=nim>+<file nim>
 let one = (1, 1.0, "one") let one = (1, 1.0, "one")
 echo one    #=> (1, 1.0, "one") echo one    #=> (1, 1.0, "one")
-</codeprism>+</file>
  
 タプルの各要素にアクセスするには''[]''とインデックスを使います。 タプルの各要素にアクセスするには''[]''とインデックスを使います。
  
-<codeprism lang=nim>+<file nim>
 let one = (1, 1.0, "one") let one = (1, 1.0, "one")
 let i = one[0] let i = one[0]
行 232: 行 233:
 echo f    #=> 1.0 echo f    #=> 1.0
 echo s    #=> one echo s    #=> one
-</codeprism>+</file>
  
 タプルを''let''ではなく''var''で宣言すれば、要素に変更を加えることも出来ます。 タプルを''let''ではなく''var''で宣言すれば、要素に変更を加えることも出来ます。
行 238: 行 239:
 タプルは要素を指すインデックスに名前を付けることが出来ます。これをフィールド名と呼ぶことにします。 タプルは要素を指すインデックスに名前を付けることが出来ます。これをフィールド名と呼ぶことにします。
  
-<codeprism lang=nim>+<file nim>
 let one: tuple[ival: int, fval: float, name: string] = (ival: 1, fval: 1.0, name: "one") let one: tuple[ival: int, fval: float, name: string] = (ival: 1, fval: 1.0, name: "one")
 echo one    #=> (ival: 1, fval: 1.0, name: "one") echo one    #=> (ival: 1, fval: 1.0, name: "one")
-</codeprism>+</file>
  
 やはり、型推論によって明示的な型の指定は省略できます。 やはり、型推論によって明示的な型の指定は省略できます。
  
-<codeprism lang=nim>+<file nim>
 let one = (ival: 1, fval: 1.0, name: "one") let one = (ival: 1, fval: 1.0, name: "one")
 echo one    #=> (ival: 1, fval: 1.0, name: "one") echo one    #=> (ival: 1, fval: 1.0, name: "one")
-</codeprism>+</file>
  
 各フィールドにアクセスするには''.フィールド名''とします。 各フィールドにアクセスするには''.フィールド名''とします。
  
-<codeprism lang=nim>+<file nim>
 let one = (ival: 1, fval: 1.0, name: "one") let one = (ival: 1, fval: 1.0, name: "one")
 let i = one.ival let i = one.ival
行 260: 行 261:
 echo f    #=> 1.0 echo f    #=> 1.0
 echo s    #=> one echo s    #=> one
-</codeprism>+</file>
  
 タプルを''let''ではなく''var''で宣言すれば、フィールドの値に変更を加えることも出来ます。 タプルを''let''ではなく''var''で宣言すれば、フィールドの値に変更を加えることも出来ます。
  
-====== その他のコンテナ ======+===== その他のコンテナ =====
  
-これまで見てきたコンテナは、順序付けられたコンテナでした。その他のコンテナについても少しだけ触れておきます。+これまで見てきたコンテナは、シーケンシャルに順序付けられたコンテナでした。その他のコンテナについても少しだけ触れておきます。
  
 キーと値のペアを格納するコンテナはテーブル(table)という名前で提供されています((他の言語でマップ(map)や辞書(dictionary)と呼ばれるものです))。テーブルを利用するには、''import std/tables''として、標準ライブラリのtablesモジュールをインポートする必要があります。 キーと値のペアを格納するコンテナはテーブル(table)という名前で提供されています((他の言語でマップ(map)や辞書(dictionary)と呼ばれるものです))。テーブルを利用するには、''import std/tables''として、標準ライブラリのtablesモジュールをインポートする必要があります。
  
  
-数学の集合を表すsetが組み込みでサポートされていますが、多くの言語のsetとは違い、テーブルの値を持たないバージョンのようなものではなくもっと限定的なものです。他の言語のsetような用途の広いsetが必要ならば、''import std/sets''として、標準ライブラリのsetsモジュールをインポートする必要があります。このモジュールではHashSetが提供されています。+数学の集合を表すsetが組み込みでサポートされていますが、上記のテーブルの値を持たないバージョンのようなものではなくもっと限定的なものです。他の言語のsetような用途の広いsetが必要ならば、''import std/sets''として、標準ライブラリのsetsモジュールをインポートする必要があります。このモジュールによりHashSetが利用できるようになります。
  
  
tutorial/nim/containers.1710160569.txt.gz · 最終更新: 2024/03/11 21:36 by freemikan

特に明示されていない限り、本Wikiの内容は次のライセンスに従います: CC0 1.0 Universal
CC0 1.0 Universal Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki