gpt4 book ai didi

f# - 应该如何定义 F# actor 函数以避免消息装箱?

转载 作者:行者123 更新时间:2023-12-01 04:59:43 24 4
gpt4 key购买 nike

Akka.NET 提供了一个 F# API,可以轻松地将 Akka Actor 定义为 Akka 邮箱上的 F# 函数。只要 Actor 处理的所有消息都可以使用一个可区分的联合来描述,那么 Actor 邮箱就是强类型的。问题在于,将所有消息定义放在一个类型(可区分的联合)中通常会使这种类型变得困惑:参与者经常响应不同类别的消息,例如远程客户端发送的消息和内部通信中使用的消息。例如,参与者可以生成内部作业并通过内部组件获得通知。使用不同的(内部)类型来定义这些内部消息是有意义的,但是 Actor 的邮箱 chages 不再是强类型,并且 Actor 的函数如下所示:

    let rec loop () =

actor {
let! message = mailbox.Receive ()
match box message with
| :? PublicMessage as msg -> handlePublicMessage msg
| :? PrivateMessage as msg -> handlePrivateMessage msg
| _ -> raise (InvalidOperationException(sprintf "Invalid message type %A" message))

return! loop ()
}

loop ()

我不喜欢这里的是,这种方法带走了 F# 的核心优势之一:类型推断。相反,我们必须将消息装箱以将它们转换为 Object 类型,然后将它们转换为我们期望的类型。

这种方法有两种选择:
  • 始终列出同一类型下的所有消息案例。糟糕,糟糕,糟糕。
  • 为每个消息类型定义一个参与者类型。恕我直言,这甚至是值得的,因为创建新 Actor 类型的决定不应受语言特定约束的驱动。

  • 我检查了 Akka.NET 训练营的代码,他们使用的是第一种方法 - 使用消息装箱和强制转换。这是最好的吗?

    最佳答案

    好的,在我看来有两个问题 - 内部消息和装箱/类型安全。

    据我了解 Actor 模型,没有私有(private)消息。 Actor 要么可以响应消息,要么不能。如果您真的想要一个异步私有(private)逻辑,我建议在处理公共(public)消息期间使用异步函数,而不是其他参与者消息,因为它必须是公共(public)的。

    为了类型安全,虽然我还没有尝试过,但似乎有另一种方法可以避免计算表达式产生actors并使用提供的泛型actorOf函数改为:

    let handleMessage message =
    match message with
    | PublicMessage as msg -> handlePublicMessage msg
    | PrivateMessage as msg -> handlePrivateMessage msg
    | _ -> raise (InvalidOperationException(sprintf "Invalid message type %A" message))

    let actorRef = spawn system "my-actor" <| actorOf handleMessage

    它基本上是您的选项 1 的类型安全替代方案。我个人认为在一个联合类型中列出所有支持的消息类型没有问题。要么 Actor 知道它的消息(最好有默认的回退),要么你想完全面向对象并且没有类型,只有装箱的动态消息。

    更多信息,例如这里的文档: http://getakka.net/docs/FSharp%20API#creating-actors-with-actor-computation-expression

    关于f# - 应该如何定义 F# actor 函数以避免消息装箱?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36470453/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com