ふと、Seq.tryFindの変な(誰得な)使い方を思いついた。F#でbreakとcontinue再び。
以前、「F#で楽々breakとcontinue。継続モナドまじパネぇっす!」を書きました。
確かに楽々ではあるんですが、継続モナドとかマジで難しいですよ。
しかも、Visual Studioでデバッグとかまともにできないですし...(´・ω・`)ショボーンな気持ちになっちゃいます。
F#でbreakとcontinue再び
ふと、Seq.tryFindの変な使い方を思いついちゃいました。
ループのbreakとcontinueっぽいものを表現するのに利用できるのではないか、と。
例えば、こんな風に書けます。「do! continue' else」のところがカッコワルイのはご愛嬌。
open System printfn "%s" "----- for" let hoge = let x = ref "/(^o^)\" loop {for i in [1..10] do if i = 5 then printfn "%s" "five" do! continue' else if i = 2 then printfn "%s" "two" do! continue' else printfn "%d" i if i = 7 then printfn "%s" "!!!" x := "\(^o^)/" return break' printfn "%d" i printfn "%s" "!" } !x hoge |> printfn "%s" printfn "%s" "----- while" let fuga = let x = ref "/(^o^)\" loop {let i = ref 0 while !i < 6 do i := !i + 1 if !i = 5 then printfn "%s" "five" do! continue' else if !i = 2 then printfn "%s" "two" do! continue' else printfn "%d" !i if !i = 7 then printfn "%s" "!!!" x := "\(^o^)/" return break' printfn "%d" !i printfn "%s" "!"} !x fuga |> printfn "%s" Console.ReadLine () |> ignore
実行結果
----- for 1 ! two 3 ! 4 ! five 6 ! 7 !!! \(^o^)/ ----- while 1 ! two 3 ! 4 ! five 6 ! /(^o^)\
LoopBuilder
Seq.tryFindの使い方が変ですw optionの使い方が変ですw
// へぼいループビルダー type LoopBuilder () = let while' gd body = (fun _ -> let b = gd() if b then if Option.isSome (body ()) then Some () else body () |> (fun _ -> None) else Some ()) |> Seq.initInfinite member this.While(gd,body) = while' gd body |> Seq.tryFind (fun x -> Option.isSome x) |> ignore member this.For (s, f) = s |> Seq.tryFind (fun x -> Option.isSome (f x)) |> ignore member this.Zero () = None member this.Combine (a,b) = a |> function |Some x -> Some x |_ -> b() member this.Return (x) = x member this.ReturnFrom (x) = Some x member this.Bind (m,f) = m |> function |Some x -> f x |> Some |_ -> None member this.Delay f = f member this.Run f = f () let break' = Some () let continue' = None let loop = LoopBuilder ()
わー!まったく難しいことをしていないシンプルな実装で、ループのbreakとcontinueな動作を表現できちゃったっぽいよ?
でも、やっぱり「do! continue' else」の部分がトテモカコワルイ。誰得かと(´・ω・`)
Imperative computation builder
ちゃんとカッコヨクやりたい人は、tomaspさんの「 Imperative computation builder 」あたりをあたった方が間違いなくよいです。
http://tomasp.net/blog/imperative-ii-break.aspx
http://fssnip.net/40
お知らせ
第61回CLR/H勉強会(TechParty2011)で、F# MVPのぶひささん( @nobuhisa_k )と、ASP.NET MVPさかもとさん( @jsakamoto )と、「F#パネルディスカッション 2011」に登壇します。F#の魅力についてお話したいと思います。
CLR/H 公式ページ
http://clr-h.jp/
TechParty2011
http://techparty2011.iinaa.net/