7章のつづき。
まずは配列。配列はサイズ固定でミュータブル。要するに、メモリ上にべたっと領域があるってことですね。
- 配列式。
[| 1; 2; 3 |]
- Array.zeroで配列の確保と初期化が出来る。ゼロで初期化したければzeroCreateを使う
- 多次元配列はインデックスの開始を0じゃなく出来る
- Array2D.zeroCreateBasedを使う
- なんのためにそんなことをするんだろう?
そして、シーケンス。シーケンスは同じ型の値の列で、Consリスト(List)かメモリマップ(Array)かは気にしない抽象化概念。 で、実態としては(Pythonと同じ意味で)ジェネレーターになっている。つまり取り出すまで実際にメモリ上に値はないし、遅延評価される。
Seqライブラリにどんな関数があるかは・・・まあ、Listでみたのと変わらない。
- List, Array, Seqモジュールはopen出来ない。RequireQualifiedAccess属性が付いているため。なので必ずList.mapのように使う
- mapが呼ばれたとして、それがList.mapなのかArray.mapなのかSeq.mapなのか見分けるのは困難だからというのが理由
あと、古い.NET Frameworkのコレクションがseq<'T>
互換じゃないってエラーが出る場合、
Seq.cast<'t>
すればいい・・・と書いてあって、例としてMatchCollectionが例に挙げられているんだけど、これは直っちゃったっぽい
> open System.Text.RegularExpressions;; > let re = Regex("\d+");; val re: Regex = \d+ > let m = re.Matches("R171 R176 R1 R2");; val m: MatchCollection > m |> Seq.map (fun m -> m.Value);; // 本だとここがエラーになる val it: seq<string> = seq ["171"; "176"; "1"; "2"]
- Seq.unfold
- foldの逆でシーケンスを生成する。生成の為の関数は'a -> ('b * 'a) option型になる。('b * 'a)の'bが要素になって、次の要素が'aを引数に続けて作られる。
- Seq.cache
- Lazy<'T>のようなキャッシュ機能をseq<'T>に後付けする
- SeqはListやArrayと違って構造的な型ではなく、参照型。なので
=
で比較すると同値ではなく同一かがチェックされる- 等値性をチェックしたければcompareWithを使う。
次はSet。Setは常に整列済み、重複なしのイミュータブルな要素を持つ。つまり集合。実装としては二分木になってる。 Setモジュールの関数はこんな感じ
- union(和)
- difference(差)
- intersect(積)
- isSubset, isSuperset, isProperSubset(真部分集合), isProperSuperset
- add, remove
- .NET FrameworkにもHashSet, SortedSetがあるけど、こいつらはイミュータブル
最後はMap。2要素のタプルのリストからmap関数で生成出来る。Mapモジュールはこんな感じ。
- find, tryFind
- containsKey
- findKey( 型が('a -> 'b -> bool) -> Map<'a,'b> -> 'a。つまり、k,vが渡ってきて、それを使ったチェックに通った要素が返ってくる)