Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

F#で遊んでみる(9)

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が渡ってきて、それを使ったチェックに通った要素が返ってくる)