パケットの送受信量(F#) - ループとbreak
元ネタ
パケットの送受信量 (C#)(F#) - SIN@SAPPOROWORKSの覚書
http://d.hatena.ne.jp/spw0022/20111116/1321437712
F#のwhileにbreakが無いのを知って愕然とした。F#では通常、whileは使用しないのかな? URL
確かにC#やVB、Javaなどの手続き型言語でのプログラミングに慣れていると、最初はそう思っちゃいますよね。
これぞ「ループで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
様々な角度から 物事を見ても、自分を見失わずにありたい。
補足
無限リスト方式が好き。無限リストに対して break キーが押されるまでの Where フィルタ書いて。でも無限リストを書くのに、F# 、構文長過ぎね? Seq.initInfinite とか。
2011-11-16 22:57:46 via web
initInfinite はぜんぜん infinite じゃないのであまり使わなかったり。
2011-11-16 22:59:58 via web
[1...] とかのノリで書けたらいいのになぁ。
2011-11-16 23:01:18 via web
@igeta オーバーフロー gkbr...
2011-11-16 23:08:39 via web to @igeta
let initEternal f = Seq.unfold (fun i -> Some(f i, i+1)) 0
2011-11-16 23:30:39 via web
エターナルアンホールド!!
中二っぽくていいね。
@zecl MSDN の「反復処理は Int32.MaxValue まで続行されます」からしてふつーに打ち切られて終わるのかと思いきや InvalidOperationException の罠ですねわかります。
2011-11-16 23:45:14 via web to @zecl
@igeta ソース見るとそうなってますね。罠としかいいようがない罠!
2011-11-16 23:50:05 via web to @igeta
@zecl Seq.reduce (fun _ x -> x) (Seq.initInfinite id) とかして実証あるのみッ!誤 しかし21億数えるのってけっこう時間かかるのねん。
2011-11-16 23:54:52 via web to @zecl
@igeta さすがに実証はする気にはなれませんでしたw
2011-11-17 00:00:10 via web to @igeta
ということで、Seq.initInfiniteのご利用は計画的に。