简体   繁体   English

Scala语法了解actor中的循环和接收

[英]scala syntax understanding about loop and receive in actor

I noticed it is legal to write this scala code: 我注意到编写此scala代码是合法的:

val fussyActor = actor {
  loop {
    receive {
      case s: String => println("I got a String: " + s)
      case _ => println("I have no idea what I just got.")
    }
  }
}

I know from documentation that actor is a trait, which has loop and receive value members. 我从文档中知道actor是一个特征,它具有loopreceive值成员。 But how is it possible to stack these methods like above? 但是如何像上面那样堆叠这些方法呢? Is it implementing or overriding these methods? 它是实现还是覆盖了这些方法? I am quite confused at this syntax. 我对这种语法很困惑。 Please provide some good references/pointers. 请提供一些良好的参考/指针。

First, a standard disclaimer. 首先,是标准的免责声明。 Scala Actors have been deprecated in favor of Akka Actors. 不推荐使用Scala演员,而推荐使用Akka演员。 If you want to continue down the path of learning to use Actors with Scala, you should look into Akka instead of researching Scala Actors. 如果您想继续学习将Actor与Scala结合使用的方法,则应该研究Akka而不是研究Scala Actors。

Now, about your question. 现在,关于您的问题。 There are a couple of things in play here, so let's first start out with what you need to do in order to define a new Scala Actor. 这里有很多事情在做,所以让我们首先从定义新的Scala Actor所需要做的事情开始。 If you look at the Scala Actor trait, you see that there is one abstract method that you must provide called act():Unit . 如果查看Scala Actor特性,您会发现必须提供一种抽象方法,称为act():Unit This is a method that takes no inputs and returns no inputs. 此方法不接受任何输入,也不返回任何输入。 It defines the actors behavior. 它定义了演员的行为。 So in it's simplest form, a custom Scala Actor could be: 因此,以最简单的形式,自定义Scala Actor可以是:

class MyActor extends Actor{
  def act(){

  }
}

Now this not a very interesting actor as it does nothing. 现在,这不是一个非常有趣的演员,因为它什么也不做。 Now, one way to provide behavior is to invoke the receive method, providing a PartialFunction[Any,R] where R is a generic return type. 现在,提供行为的一种方法是调用receive方法,提供PartialFunction[Any,R] ,其中R是通用返回类型。 You could do that like so: 您可以这样做:

class MyActor extends Actor{
  def act(){
    receive{
      case "foo" => println("bar")
    }
  }
}

So now if this actor receives a message "foo", it will print "bar". 因此,现在,如果此参与者收到消息“ foo”,它将打印“ bar”。 The problem here is that this will only happen for the first message and then won't do anything after. 这里的问题是,这只会在第一个消息发生,然后在之后将不做任何事情。 To fix that. 要解决这个问题。 we can wrap our call to receive with a call to loop to make it continue to do the provided receive call for each received message: 我们可以将我们的调用包装为具有loop调用的receive ,以使其继续为receive的每条消息执行提供的receive调用:

class MyActor extends Actor{
  def act(){
    loop{
      receive{
        case "foo" => println("bar")
      }
    }
  }
}

So this is now starting to look like your example a bit more. 因此,现在开始看起来像您的示例。 We are leveraging the loop and receive methods that come with the Actor trait in order to give this actor behavior. 我们利用loopreceive Actor特性附带的方法来赋予此actor行为。 Lastly, instead of defining an explicit class as my actor, I can define one on the fly with the actor method on the Actor companion object. 最后,我可以使用Actor随播对象上的actor方法动态定义一个类,而不是将其定义为我的actor。 That method takes a function body that will be used as the act impl like this: 该方法采用一个函数体,该函数体将用作如下所示的act

def actor(body: => Unit){
  val a = new Actor {
    def act() = body
    override final val scheduler: IScheduler = parentScheduler
  }
}

So in your example, you are creating a new actor implementation on the fly and providing an impl for act that will loop and call receive continually with the partial function you supplied for message handling. 因此,在您的示例中,您正在动态创建一个新的actor实现,并为该act提供了一个impl,它将使用您提供的用于消息处理的部分函数连续循环和调用receive

Hopefully this clarifies things a bit. 希望这可以澄清一些事情。 The only method you are "overriding" (providing an impl for) is act . 您要“覆盖”(为其提供隐含)的唯一方法是act When you see loop and receive , those are not overrides; 当您看到loopreceive ,这些不是覆盖。 they are simply calls to those existing methods on the Actor trait. 它们只是调用Actor特性上的现有方法。

Actually it's illegal without import Actor._ . 实际上,如果没有import Actor._这是非法的。

Your code without that import: 您没有导入的代码:

val fussyActor = Actor.actor {
  Actor.loop {
    Actor.receive { ... }
  }
}

actor , loop and receive are methods of object Actor . actorloopreceive是对象Actor方法。

def actor(body: ⇒ Unit): Actor
def loop(body: ⇒ Unit): Unit
def receive[A](f: PartialFunction[Any, A]): A

Method actor accepts by-name Untit parameter body - some code block to execute in separate thread and creates an Actor with act method implemented using parameter body . 方法actor接受by-name Untit参数body -一些代码块以在单独的线程中执行,并创建具有使用参数body实现的act方法的Actor

Method loop accepts by-name Untit parameter body - some code block to execute in infinite loop. 方法loop接受by-name Untit参数body -一些代码块在无限循环中执行。

Method receive accepts PartialFunction as parameter f and calls f with message as parameter. 方法receive接受PartialFunction作为参数f并以消息作为参数调用f It takes message from actor associated with current thread. 它从与当前线程关联的actor获取消息。

Note that scala actors are deprecated, you should use akka actors. 请注意,scala actor已过时,您应该使用akka actor。 See The Scala Actors Migration Guide . 请参阅《 Scala Actor迁移指南》

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM