从 Actor 向调用者发送 None

发布于 2024-12-04 11:12:26 字数 803 浏览 5 评论 0原文

我有一个简单的 Actor,它使用 ScalaQuery 查询数据库,我已经模拟了它来测试使用它的客户端。

我想要的是,如果 ID 匹配,(模拟)Actor 会回复 Some(MyObject) ,否则回复 None 。但是,我不知道如何进行这项工作。这是我到目前为止的代码:

def receive = {
  case FetchSomething(someId) => {
    if (someId == 1234) self.channel ! someObject
    else self.channel ! None
  }
}

但是,它不是在客户端代码中返回 None ,而是返回 Some(None) - 这当然会让我的客户端感到困惑。我希望客户端的工作方式是这样的:(

val object = persister !! FetchSomething(1337) match {
    case myObject: Some[MyObject] => myObject
    case _ => None
}

当然,上面的内容可能是错误的 - 而不是 Some,它可能是 Option

我怎样才能实现这?也许更具体地说,我如何通过 self.channel 发回 None ,以便在匹配它时,它是 None 而不是 Some(None)

I have a simple Actor that queries a database using ScalaQuery, which I've mocked for a test of a client using it.

What I want is for the (mock) Actor to reply with Some(MyObject) if the ID matches up, and None otherwise. However, I can't figure out how to make this work. Here's the code I have so far:

def receive = {
  case FetchSomething(someId) => {
    if (someId == 1234) self.channel ! someObject
    else self.channel ! None
  }
}

However, instead of returning None in the client code, it returns Some(None) - which, of course, confuses my client. How I want the client to work is something like this:

val object = persister !! FetchSomething(1337) match {
    case myObject: Some[MyObject] => myObject
    case _ => None
}

(of course, the above may just be wrong - instead of Some, it could be Option)

How can I achieve this? Perhaps more specific, how can I send a None back through self.channel so when matching it, it's None and not Some(None)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

同展鸳鸯锦 2024-12-11 11:12:26

错误在于客户端,它误解了回复,不遵循 AKKA 协议。来自 Akka 文档

这个!!方法返回一个 Option[Any] ,它将是 Some(result)
如果成功返回,或者如果调用超时则无。

因此,如果回复为 None,则客户端为 Some(None)。如果回复是 Some(12),您会得到 Some(Some(12))。如果客户端收到 None,则不应该意味着参与者回复 None,而是意味着参与者没有回复。

这是AKKA协议,这意味着客户端应该使用

case Some(answer) => process answer
case None => actor did not reply

Then处理回复,如果你的actor碰巧回复了一个Option[Something],那就是你的协议,这是另一层:

case Some(answer) => /* your protocol */ answer match { 
  case Some(actualValue) => reply had actualValue
  case None => None was the reply
}
case None => actor did not reply

当然,你也可以写

case Some(Some(actualValue)) => 
case Some(None) => 
case None => 

一个旁注,不要与x: Some[A]匹配(匹配泛型类型时不要给出类型参数)。它不起作用,它不会验证您是否有 Some[Something],但不会验证 SomethingA (请参阅类型擦除,编译器会给出警告)。您想要与 case Some(x: A) 匹配,它会为您提供 xSome 的内容,这是您通常想要的。如果您实际上想要 Some 而不是其内容,case s @ Some(x: A) 会将 s 绑定到 Some 实例,x 为其内容。如果您对此不感兴趣,请使用 _ 代替 x。

如果知道选项里面的类型是A,那就不用提了,直接写
case Some(x)case s: Some(_)

The fault is in the client, which misinterpret the reply, not following AKKA protocol. From the Akka documentation :

The !! method returns an Option[Any] which will be either Some(result)
if returning successfully, or None if the call timed out.

So if reply is None, client Some(None). If reply is Some(12) you get Some(Some(12)). If client receives None, it should not means the actor replied None, it means the actor did not reply.

This is AKKA protocol, and it means client should process reply with

case Some(answer) => process answer
case None => actor did not reply

Then if your actor happens to reply with an Option[Something], that is your protocol, which is another layer:

case Some(answer) => /* your protocol */ answer match { 
  case Some(actualValue) => reply had actualValue
  case None => None was the reply
}
case None => actor did not reply

Which of course, you can also write

case Some(Some(actualValue)) => 
case Some(None) => 
case None => 

A side note, do not match with x: Some[A] (do not give the type parameter when matching on a generic type). It does not work, it will not verify that you have a Some[Something], but not that Something is A (see type erasure, the compiler gives a warning). You want to match with case Some(x: A) which gives you the content of the Some in x, what you normally want. If you actually want the Some rather than its content, case s @ Some(x: A) will bind s to the Some instance, x to its content. Use _ instead of x if you are not interested in it.

If it is known that the type inside the option is A, then do not mention it, just write
case Some(x), case s: Some(_)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文