F#で集合を扱う その2
名前空間:Microsoft.FSharp.CollectionsのSetモジュールについて。
Set が生成する集合オブジェクトはイミュータブル(immutable)つまり変更不可な値です。
以下のコードでAdd メソッドを呼び出していますが、1行目で生成した集合オブジェクトの内容を書き替えているわけではありません。
- let s1 = set [1; 2]
- s1.Add 10
- s1.Add 20
2~3行目は Add メソッド呼び出し毎に s1に要素を加えた新規の集合オブジェクトが生成されています。代入(束縛)先の変数が存在しないので2行目と3行目の計算結果はそれぞれ捨てられます。
F# Interactive で上記コードを実行して変数 s1 の値を調べてみます。
> s1;;
val it : Set<int> = set [1; 2]
s1の値はAdd の呼び出しを実行しても変化していないことが分かります。
もしs1に新たに要素を追加した集合オブジェクトが欲しければ、オブジェクトを新たに生成して別の変数(下記のコードでは s2)に代入(束縛)する必要があります。
- let s1 = set [1; 2]
- let s2 = s1.Add(10).Add(20)
2行目で s1 の内容にさらに要素(10、20)を加えた集合オブジェクトを生成して変数 s2 に代入(束縛)しています。
ここで、変数 s1 と変数 s2 の内容を調べてみます。
> s1;;
val it : Set<int> = set [1; 2]
> s2;;
val it : Set<int> = set [1; 2; 10; 20]
s1は要素は依然2つのままで初期状態から変化していませんが、新たに生成された集合オブジェクト s2には4つの要素が存在しています。
次に同様に集合を扱う機能を持つ HashSet の動作を調べてみます。名前空間:System.Collections.Generic にこのクラスはあります。このクラスによって生成されるオブジェクトはミュータブル(mutable)つまり変更可能です。
- open System.Collections.Generic
- let hs1 = HashSet([1; 2])
- hs1.Add 10
- hs1.Add 20
2行目で生成された hs1 の値に3~4行目の HashSet.Add で新たな要素を加えていって次々と更新していきます。
> hs1;;
val it : HashSet<int> = seq [1; 2; 10; 20]
HashSet ではAddメソッドによって内容が書き変えが可能です。Set の同名のメソッドとは動作が異なり、呼び出しによって新たな集合オブジェクトが生成されることはありません。