らくがき

2008/04/21

TrueCrypt

HDD丸ごと暗号化しちゃいます@@

2008/04/09

[F#] .NETライブラリから返される「null値」はどのように扱えばよい?

boxing 機能を用いることで、「null値」と比較できます。
box (value) <> null
パターンマッチで判断することもできます。
match x.ReadLine() with 
| null -> None 
| line -> Some(line)
.NETライブラリで最終的に null値 を返す関数を扱うときの多相的関数(ジェネリック関数)
#light

/// Usage: "SeqGivenFuncTillNull<string>(sr.ReadLine)"
let SeqGivenFuncTillNull<'a when 'a:not struct> (f:unit->'a) :seq<'a> =
  seq {
        let v = ref (f()) in
        while box (!v) <> null do
          yield !v
          do v := f()
      }
StringReader を例にすると、以下のようになります。
let str = "testeseテスト!\ndeoweiru!ewp!";;
let sr = new StringReader(str);;

let lineSeq = SeqGivenFuncTillNull<string>(sr.ReadLine);;

let main =
  for line in lineSeq do
    printfn "%s" line
  done
StringReader は TextReader を継承しているので、 TextReader を拡張し、"SeqGivenFuncTillNull"を意識しないようにもできます。
/// Extend IO.TextReader.
type System.IO.TextReader with
  member it.to_string_seq = SeqGivenFuncTillNull<string>(it.ReadLine)

// Usage:
let s = "first line\nsecond line\nthird line\n"
let sr2 = new System.IO.StringReader(s)
for line in sr2.to_string_seq do   // Life is good :)
  printfn "%s" line;;
また、F#で扱いやすいように Option で包むことも可能です。
type System.IO.TextReader with 
    member x.TryReadLine() = 
        match x.ReadLine() with 
        | null -> None 
        | line -> Some(line)

let SeqGivenFuncTillNull2 (f:unit->'a option) :seq<'a> =
  seq {
        let v = ref (f())
        while (!v) <> None do
          yield Option.get (!v)
          do v := f()
      }

Labels:

2008/04/06

[F#] F#でのSTM(Software Transactional Memory)

Software Transactional Memory for F# http://cs.hubfs.net/blogs/hell_is_other_languages/archive/2008/01/16/4565.aspx wikiによると、STMとは 「データベーストランザクションに似た並行性制御機構であり、並列計算を行う際の共有メモリへのアクセス法である。」 とある。 つまり、複数のスレッドから読み書きされるデータの整合性を保証する役目ってことかな。 従来のロックベースの代替案として注目を集めているみたい。 そんなわけで、リンク先にあるのは、「STMをF#で使えるようにしてみましたー!」的なライブラリ (コア部分はC#で書かれてるんだって) おまけとして「サンタクロース問題」のソース付  

Labels:

2008/04/02

[F#] 二分木(binary tree)専用のmap関数

Memo : Node(左の木, このノードの値, 右の木)
type 'a tree = Nil | Node of ('a tree) * 'a * ('a tree)
再帰的: (通りがけ順, 中置記法)
let rec map0 f t =
  match t with
    Nil -> Nil
  | Node(l,v,r) -> let v' = f v in Node(map0 f l, v', map0 f r)
末尾再帰的: (帰りがけ順, 逆ポーランド記法)
let map3 f tree =
   let rec map' subtree build =
       match subtree with
           | Nil -> build Nil
           | Node(l, v, r) ->
               let v' = f v in
               map' l (fun l' -> map' r (fun r' -> Node(l', v', r') |> build)) in
   map' tree (fun x -> x)
テスト用コード:
// 関数のリスト
let maps : (string * (('a->'b) -> 'a tree -> 'b tree)) list = 
   [
    "map0 (non-tail-recursive):", map0;
    "map3 (Vladimir's functional):", map3;  
   ]

// 木の表示
let rec print_tree t = match t with
  Nil -> printf ""
| Node(l,v,r) ->
    printf "(";
    print_tree l; 
    printf "%d" v;
    print_tree r;
    printf ")"
;;

// テスト用の木の用意と、関数のリストに登録されている関数の実行、そして木の表示
let _ =
  let tree = Node(Node(Node(Nil,1,Nil),2,Node(Nil,3,Nil)),5,Node(Node(Nil,6,Nil),7,Node(Nil,8,Nil))) in
  print_tree tree; printf "\n";
  List.iter (fun (s,map) -> print_tree (map (fun x -> x+1) tree); printf "\n") maps
;;
テスト用の木構造 結果:
(((1)2(3))5((6)7(8)))  -- テスト用の木
(((2)3(4))6((7)8(9)))  -- 関数適用後の木 -- map0
(((2)3(4))6((7)8(9)))  -- 関数適用後の木 -- map3
再帰的な定義は、非常に簡潔でわかりやすく、実行速度も速い。しかし、メモリ消費量が大 末尾再帰的な定義は、簡潔ではなく、実行速度も遅い。しかし、メモリ消費量が小  

Labels: