Erlang style message passing is a great way of simplifying concurrency. The open source Retlang library aims to bring some of the benefits to .Net languages like C# and VB.Net. Whereas F# has built-in message passing support with the MailboxProcessor also referred to as Agents. To compare Retlang against F# Agents I have coded up the Retlang Summation example (171 lines) as an equivalent F# implementation (41 lines):
type Agent<'a> = MailboxProcessor<'a>
type Summation =
| Add of int
| Total of AsyncReplyChannel<int>
and SummationAgent () =
let agent = Agent.Start ( fun inbox ->
let rec loop total =
async {
let! message = inbox.Receive()
match message with
| Add n -> do! loop (n + total)
| Total reply -> reply.Reply(total)
}
loop 0
)
/// Adds value to total
member this.Add n = Add(n) |> agent.Post
/// Returns total and ends computation
member this.Total () = (fun reply -> Total(reply)) |> agent.PostAndReply
/// Invokes specified function with numbers from 1 to limit
let numberSource f limit =
async {
for i = 1 to limit do
f i
if i % 10 = 0 then System.Console.WriteLine("{0}\t({1})",i,limit)
}
do /// Summation agent instance
let agent = SummationAgent ()
// Post series of numbers to summation agent in parallel
[100;50;200]
|> Seq.map (numberSource agent.Add)
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
// Get total
let value = agent.Total ()
System.Diagnostics.Debug.Assert(26425 = value);
value |> System.Console.WriteLine
If you compare this to the Retlang example implementation, it should be clear that C# is missing the easy message definition (discriminated unions) and pattern matching part of message passing. You may also notice that in the F# version, the functionality is accomplished, not only without locks, but also without any low-level threading primitives (like AutoResetEvent). However, if you find yourself constrained to C# development then Retlang is definitely worth a look.