开发者

Instantiating and starting a Scala Actor in a Map

I'm experimenting with a map of actors, and would like to know how to instantiate them and start them in one fell swoop...

import scala.actors.Actor
import scala.actors.Actor._
import scala.collection.mutable._

abstract class Message
case class Update extends Message

object Test {
    val groupings = "group1" :: "group2" :: "group3":: Nil
    val myActorMap = new HashMap[String,MyActor]

    def main(args : Array[String]) {
        groupings.foreach(group => myActorMap += (group -> new MyActor))
        myActorMap("group2").start
        myActorMap("group2") ! Update
    }
}

class MyActor extends Actor {
    def act() {
        loop {
            react {
                case Update =>
                    println("Received Update")
                case _ =>
                    println("Ignoring event")
            }
        }
    }   
}

The line:

    myActorMap("group2").start

will grab the second instance, and let me start it, but I would like to be able to do something more like:

        groupings.foreach(group => myActorMap += (group -> (new MyActo开发者_StackOverflow中文版r).start))

but no matter how I wrap the new Actor, the compiler complains with something along the lines of:

type mismatch; found : scala.actors.Actor required: com.myCompany.test.MyActor

or various other complaints. I know it must be something simple to do with anonymous classes, but I can't see it right now. Any suggestions? Thanks in advance!!


The problem with start is that it doesn't know the true type of your actor. Thus, it returns a generic one. To get around this, you need a compact way to start it and still return the actor you actually have (not a superclass). Actually, that sounds like a useful capability in general, doesn't it?--to take an object, have it do something, and then return the object?

class SideEffector[A](a: A) {
  def effect(f: A => Unit) = { f(a); a }
}
implicit def everythingHasSideEffects[A](a: A) = new SideEffector(a)

Now you can

(new MyActor).effect(_.start)

and the type will be preserved. (If you're not using Scalaz, this sort of capability is so useful in general that you may want to drop it into your personal library of handy code snippets. It's in mine. You have one, don't you?)


How about this:

    def main(args : Array[String]) {
      groupings.foreach {
        group =>
        val actor = new MyActor
        actor.start
        myActorMap += (group -> actor)
      }

      myActorMap("group2") ! Update
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜