I'm trying to code some Clojure style Agents in F# using MailboxProcessors. Here's what I have so far:
namespace GameEngine
type Agent<'T>(inital:'T) =
let mutable state:'T = inital
let queue = new MailboxProcessor<'T -> 'T>( fun inbox ->
let rec loop count =
async {
let! msg = inbox.Receive()
state <- msg(state)
return! loop(count + 1)
}
loop 0)
do
queue.Start()
member self.Send(action:'T -> 'T) =
queue.Post(action)
mem开发者_如何学Gober self.Deref() =
state
So the basic idea is that we have a mutable state that can be updated by calling .Send(). My question is, will my messages ever be out of order? If msg A is sent before B will the async function above always process A before B?
Seems like there should be a class like this already in F#? Am I reinventing the wheel?
If msg A is sent before B will the async function above always process A before B?
Yes. (You can see the code for Mailbox
http://fsharppowerpack.codeplex.com/SourceControl/changeset/view/54799#970072
browse to compiler\2.0\Nov2010\src\fsharp\FSharp.Core\control.fs, and eventually see e.g.
member x.Post(msg) =
lock syncRoot (fun () ->
arrivals.Enqueue(msg);
...
which shows it's just a queue under a lock.)
Seems like there should be a class like this already in F#? Am I reinventing the wheel?
Well, it's not immediately clear to me how this is different from just updating a mutable global variable willy-nilly (modulo atomicity of simultaneous updates; you said "before" in the question, so I am unclear if that aspect matters to you). What's the context for wanting this?
There is no built-in implementation of the Clojure-style Agent.
I also at one point worked up a quick and dirty F# implementation similar to yours, but did not take the time to consider all the correctness issues involved; in particular, is it not true that 'T may be a value type (a struct
) larger than 64 bits (or 32 bits as the case may be) which could cause a tear (I presume that Clojure like Java doesn't have structs to worry about here). Perhaps an F# generic type constraint ('T when 'T : not struct
) would be needed?
精彩评论