简体   繁体   中英

scala syntax understanding about loop and receive in actor

I noticed it is legal to write this scala code:

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. 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. 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.

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. If you look at the Scala Actor trait, you see that there is one abstract method that you must provide called 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:

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. 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". 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:

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. 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. That method takes a function body that will be used as the act impl like this:

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.

Hopefully this clarifies things a bit. The only method you are "overriding" (providing an impl for) is act . When you see loop and receive , those are not overrides; they are simply calls to those existing methods on the Actor trait.

Actually it's illegal without import Actor._ .

Your code without that import:

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

actor , loop and receive are methods of object 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 .

Method loop accepts by-name Untit parameter body - some code block to execute in infinite loop.

Method receive accepts PartialFunction as parameter f and calls f with message as parameter. It takes message from actor associated with current thread.

Note that scala actors are deprecated, you should use akka actors. See The Scala Actors Migration Guide .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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