Akka演员中的接收方法

receive method in Akka actor

我在 Akka actor 实现中有以下接收方法的实现。

override def receive: Receive = {
  case SetRequest(key, value) =>{
    log.info("Received SetRequest - key:{} ,value:{}", key,value)
    map.put(key,value)
    sender() ! Status.Success
  }
  case GetRequest(key) => {
    log.info("Received GetRequest for - key:{}", key)
    val response: Option[Object] = map.get(key)
    response match {
      case Some(x) => sender() ! x
      case None => sender() ! Status.Failure(new KeyNotFoundException(key))
    }
  }
  case o => Status.Failure(new ClassNotFoundException())
}

我在这里有几个问题。

在Actor.scala中,接收定义为:

def receive: Actor.Receive

Actor.Receive 是:

type Receive = scala.PartialFunction[scala.Any, scala.Unit]

那么我在receive中的代码如何符合Actor.Receive?

其次,这种模式匹配是什么风格?receive 似乎没有收到任何参数,那么我实际上要匹配什么?例如,在代码中我匹配响应,这是有意义的,因为响应是在它之前计算的模式匹配。

偏函数来自数学,与全函数相对。为所有输入定义了总函数,如下所示:

val f = (i: Int) => i + 10

函数 f 为 Int 类型的任何输入产生有效结果。 但是这个部分函数:

val g = (i: Int) => 10/i

不会(零会导致错误)。

在 Scala 中,您可以像这样创建这些特殊函数:

val h: PartialFunction[Int, Int] = {
  case i: Int if i != 0 => 10/i
}

它有一个方法 isDefinedAt 可用于检查它是否为给定输入生成有效结果:

h.isDefinedAt(0) // false
h.isDefinedAt(5) // true

您可以像调用普通函数一样调用部分函数:

h(5)

但它们还允许您像使用 orElse 的常规函数​​一样链接和组合它们。示例:

val x: PartialFunction[Int, String] = {
  case i: Int if i = 10 => "ten"
}

val y: PartialFunction[Int, String] = {
  case i: Int if i = 5 => five"
}

val z = y orElse x

z(10) // "ten"
z(5)  // "five"
z(0)  // MatchError

他们一个人可以处理一个案件,他们可以处理两个。

关于你的第二个问题: receive是Actor trait中一个未实现的方法。它将在 Akka 实现的某处随您的消息一起被调用。它 returns 是一个部分函数,​​因此它可以与默认的 Akka 消息结合使用,例如 PoisonPill 等等。

So how does my code in receive conforms to Actor.Receive? ... What is this style of pattern matching?

在Scala中,case是一种常见的偏函数。例如:

val oneOrTwo: PartialFunction[Int, String] = {
  case 1 => "one"
  case 2 => "two"
}
// oneOrTwo: PartialFunction[Int,String] = <function1>

val reciprocal: PartialFunction[Double, Double] = { case i if i != 0 => 1 / i }
// reciprocal: PartialFunction[Double,Double] = <function1>

因此 case 部分函数可用于实现具有 PartialFunction[Any, Unit] 签名的 receive

Any 参数类型允许您使用 case 来检查您希望的任何类型的 input(例如 SetRequest(key, value)GetRequest(key)你的示例代码)。

在return类型上,Unit允许您放入任何消息处理代码(例如示例代码中的sender() ! Status.Successresponse match {...})并且不需要一个 return 值。

receive seems to receive no argument, so what am I actually trying to match?

你的class扩展了Actor,所以在覆盖receive时,你需要实现traitActor中声明的方法(见下文,来自Akka source code) 您已经用 case 部分函数完成了。

object Actor {
  type Receive = PartialFunction[Any, Unit]
  // ...
}

trait Actor {
  def receive: Actor.Receive
  // ...
}

通过扩展 Actor 和实现方法 receive,Akka 为您的 class 配备了所有消息驱动的 actor 功能,包括 mailbox 并指定了一个调度程序来提供信息发送给它的任何消息(例如来自另一个演员的 myActor ! GetRequest(key))作为 inputreceive 方法。