我有一个简单的Actor,它使用ScalaQuery查询数据库,我已经嘲笑过使用它的客户端的测试。
我想要的是(模拟)Actor如果ID匹配则回复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)
?
答案 0 :(得分:8)
故障发生在客户端,它错误解释了回复,而不是遵循AKKA协议。来自the Akka documentation:
!!方法返回一个Option [Any],它将是Some(结果) 如果成功返回,或者如果通话超时则为无。
因此,如果回复为None,则客户端为Some(None)。如果回复是某些(12)你得到一些(一些(12))。如果客户端收到None,则不应该表示actor回答None,这意味着actor没有回复。
这是 AKKA协议,这意味着客户端应该使用
处理回复case Some(answer) => process answer
case None => actor did not reply
然后,如果你的演员恰好用选项[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]
不匹配(在泛型类型上匹配时不要给出type参数)。它不起作用,它不会验证您有Some[Something]
,但Something
不是A
(请参阅类型擦除,编译器会发出警告)。您希望与case Some(x: A)
匹配,后者会为您提供Some
中x
的内容,您通常需要的内容。如果您确实需要Some
而不是其内容,case s @ Some(x: A)
会将s
绑定到Some
实例,x
绑定到其内容。如果您对它不感兴趣,请使用_
代替x。
如果已知选项内的类型为A
,则不要提及,只需写入
case Some(x)
,case s: Some(_)