ようこそ。睡眠不足なプログラマのチラ裏です。

パケットの送受信量(F#) - ループとbreak

元ネタ
パケットの送受信量 (C#)(F#) - SIN@SAPPOROWORKSの覚書
http://d.hatena.ne.jp/spw0022/20111116/1321437712


確かにC#VBJavaなどの手続き型言語でのプログラミングに慣れていると、最初はそう思っちゃいますよね。
これぞ「ループでbreak脳の恐怖!」...って、私もその道を通りました。


方法1:再帰を使う

open System
open System.Net.NetworkInformation

let ar = 
    NetworkInterface.GetAllNetworkInterfaces()
    |>Seq.map(fun n -> n,n.GetIPv4Statistics())
    |>Seq.map(fun (n,s) -> n.Description,s.BytesReceived,s.BytesSent)

let rec loop func = 
  match func () with
  | ConsoleKey.X -> () 
  | _ -> loop func 

let func () = 
  printfn "%-45s\t%-10s\t%-10s" "Description" "Recv" "Send"
  printfn "-------------------------------------------------------------------------"
  ar|>Seq.iter(fun (d,r,s) -> printfn "%-15s\t%10d\t%10d" d r s)
  printfn ""
  printfn "何かのキーを押すと更新されます(Xで終了)"
  Console.ReadKey().Key |> fun key -> Console.Clear()
                                      key
loop func 

方法2:無限シーケンスを使う

open System
open System.Net.NetworkInformation

let ar = 
    NetworkInterface.GetAllNetworkInterfaces()
    |>Seq.map(fun n -> n,n.GetIPv4Statistics())
    |>Seq.map(fun (n,s) -> n.Description,s.BytesReceived,s.BytesSent)

let func () = 
  printfn "%-45s\t%-10s\t%-10s" "Description" "Recv" "Send"
  printfn "-------------------------------------------------------------------------"
  ar|>Seq.iter(fun (d,r,s) -> printfn "%-15s\t%10d\t%10d" d r s)
  printfn ""
  printfn "何かのキーを押すと更新されます(Xで終了)"
  let key = Console.ReadKey().Key
  Console.Clear()
  key 

let infiniteSeq = Seq.initInfinite (fun _ -> func())
let run item = if item = ConsoleKey.X then 
                 Some(item)
               else None
 
Seq.pick run infiniteSeq |> ignore


ループでbreakを表現する方法は、他にもいろいろあるでしょう。


■関連リンク

F#で楽々breakとcontinue。継続モナドまじパネぇっす!
http://d.hatena.ne.jp/zecl/20110322/p1

ふと、Seq.tryFindの変な(誰得な)使い方を思いついた。F#でbreakとcontinue再び。
http://d.hatena.ne.jp/zecl/20110822/p1



様々な角度から 物事を見ても、自分を見失わずにありたい。



補足
いくつか Seq.initInfinite 関係のツイートを拾ってみました。


ということで、Seq.initInfiniteのご利用は計画的に。