在 F# API 中该如何用一种惯用的方式来处理状态,使其成为类中的私有字段?与 C# 的 ReceiveActor
不同。
这是否是一个好主意?还有其他选择吗?
let handleMessage (mailbox: Actor<'a>) msg =
let mutable i = 1
match msg with
| Some x -> i <- i + x
| None -> ()
spawn system "hello" <|
fun mailbox ->
let rec loop state =
actor {
let! msg = mailbox.Receive ()
printfn "Received %A. Now received %s messages" msg state
return! loop (state + 1) //Increment a counter for the number of times the actor has received a message
}
loop 0
完整的Akka.Net F# API文档请参见http://getakka.net/wiki/FSharp%20API
有两种解决方案,它们都使用显式递归循环定义,这是Akka F# actor的主要概念。
首先,您可以在循环定义之前定义变量,这些变量应该仅在actor的范围内可见(在下面的示例中,我已将i定义更改为引用单元格,因为可变变量无法被闭包捕获):
let actorRef =
spawn system "my-actor" <| fun mailbox ->
let i = ref 1
let rec loop () =
actor {
let! msg = mailbox.Receive()
match msg with
| Some x -> i := !i + x
| None -> ()
return! loop()
}
loop()
然而,更建议的解决方案是在消息处理期间保持状态不可变,并仅在传入下一个循环调用时进行更改,就像这样:
let actorRef =
spawn system "my-actor" <| fun mailbox ->
let rec loop i =
actor {
let! msg = mailbox.Receive()
match msg with
| Some x -> return! loop (i + x)
| None -> return! loop i
}
loop 1 // invoke first call with initial state
ReceiveActor
派生?有什么东西可以让您使用递归轮询循环? - Mark Seemann