2011-01-07 7 views
0

ich mit einer Karte von Schauspieler bin zu experimentieren, und würde gerne wissen, wie sie instanziieren und sie auf einen Schlag starten ...Instanziierung und Start einer Scala Schauspieler in einer Karte

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") 
      } 
     } 
    } 
} 

Die Linie :

myActorMap("group2").start 

wird die zweite Instanz, packen und ich lassen starten, aber ich würde etwas mehr wie können, gerne tun:

 groupings.foreach(group => myActorMap += (group -> (new MyActor).start)) 

aber egal wie ich den neuen Aktor einpacke, beschwert sich der Compiler mit etwas in der Art:

Typ Mismatch; gefunden: scala.actors.Actor erforderlich: com.myCompany.test.MyActor

oder verschiedene andere Beschwerden. Ich weiß, dass es mit anonymen Kursen etwas Einfaches zu tun hat, aber ich kann es jetzt nicht sehen. Irgendwelche Vorschläge? Danke im Voraus!!

Antwort

1

Wie wäre es damit:

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

     myActorMap("group2") ! Update 
    } 
+0

Das funktioniert, danke. –

+0

Nicht sehr FP, obwohl. Ich denke, dass Rex 'Ansatz (Continuation-Passing-Stil?) Wahrscheinlich hilft, den Code zu minimieren, wenn er in verschiedenen Kontexten verwendet wird. –

+0

Mine ist nicht CP. Es verwendet nur eine praktische quasi-funktionale Methode (mit impliziten Konvertierungen). –

3

Das Problem mit start ist, dass es nicht die wahre Art Ihres Schauspieler nicht kennt. Daher gibt es eine generische zurück. Um dies zu umgehen, benötigen Sie einen kompakten Weg, um es zu starten und immer noch den Akteur zurückzugeben, den Sie tatsächlich haben (keine Oberklasse). Eigentlich klingt das im Allgemeinen nach einer nützlichen Fähigkeit, oder? - ein Objekt zu nehmen, etwas zu tun und dann das Objekt zurückzugeben?

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

Jetzt können Sie

(new MyActor).effect(_.start) 

und die Art bleiben erhalten. (Wenn Sie Scalaz nicht verwenden, ist diese Art von Funktionalität im Allgemeinen so nützlich, dass Sie sie vielleicht in Ihre persönliche Bibliothek mit handlichen Code-Snippets einfügen möchten. Es gehört mir. Sie haben eines, oder?)

+0

Schön. Ich mag es. Etwas gelöst, was mich eine ganze Weile beschäftigt. Da ich FP im Allgemeinen neu bin, habe ich einige Probleme mit dem Umgang mit Nebenwirkungen, insbesondere in Funktionsliteralen. –

+0

Sehr cool. Ich schätze den sehr nützlichen Rat. Vielen Dank! –