Can't nobody tell me F# async is easy; it seems hard to me. I wanted to put together the simplest sample (but different from all the samples I've seen) so I could get a better understanding. Maybe thistle help someone else. I'm searching a file line by line to see if I can find a match. In this case there are only 4 lines in the file so I'm splitting the file into 2 chunks. Each... async... thing (after watching a long video on C# async lately and ending up hopelessly confused about when actual new threads are created I've given up guessing) gets 2 lines. In this sample, it's pretty handy how it stops looking after finding a match.
open System.IO open System // So we don't just print "null" to console when not found. let OptionToStr o = match o with | None -> "not found" | Some(o) -> o // Because our line gets wrapped into an option twice (once in Seq.tryPick and again in Seq.tryFind). let UnwrapOption o = match o with | None -> None | Some(o) -> o // Some(matching line) if the current chunk contains our id let ChunkContains (id:string) (chunk:string seq) = chunk |> Seq.tryPick ( fun line -> // Notice how it doesn't process all lines when it finds a match. printfn "Current: %s" line if line.Contains id then Some(line) else None ) // Skip n lines and call our search method for the current chunk let ProcessFileChunkAsync (lines:string seq) skip (func: string seq -> string option) = async { // Note: async is cranky. You have to format the curly braces a certain way or compiler will complain with strange error. return lines // return keyword required. |> Seq.skip skip |> Seq.truncate 2 |> func // 2nd parameter applied to previous partial application of ChunkContains below. } [] let main argv = let lines = File.ReadAllLines @"c:\temp\4LinesOfTrash.txt" // one of the lines is "hi mom" seq { 0 .. 1 } |> Seq.map ( fun i -> let chunkFun = ChunkContains "hi" // find the line with "hi"; partial func application ProcessFileChunkAsync lines (i * 2) chunkFun ) |> Async.Parallel // Fork |> Async.RunSynchronously // Join: Take the async results and wait for them to complete. |> Seq.tryFind ( fun item -> Option.isSome item ) |> UnwrapOption |> OptionToStr |> printfn "Result: %A" |> Console.ReadLine |> ignore 0
No comments:
Post a Comment