2011-01-07 2 views
0

Я экспериментировал с картой актеров, и хотел бы знать, как создать экземпляр их и запускать их одним махом ...инстанцировании и начать Актера Scala в карте

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

Линия :

myActorMap("group2").start 

захватит второй экземпляр, и позвольте мне начать, но я хотел бы быть в состоянии сделать что-то подобное:

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

, но независимо от того, как я обертываю нового актера, компилятор жалуется на что-то по строкам:

тип несоответствие; найдено: scala.actors.Actor требуется: com.myCompany.test.MyActor

или различные другие жалобы. Я знаю, что это должно быть что-то простое с анонимными классами, но я не вижу его прямо сейчас. Какие-либо предложения? Заранее спасибо!!

ответ

1

Как об этом:

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

     myActorMap("group2") ! Update 
    } 
+0

Это работает, спасибо. –

+0

Не очень FP. Я думаю, что подход Rex (стиль продолжения?), Вероятно, помогает минимизировать код при использовании в разных контекстах. –

+0

Шахта не СР. Он просто использует удобный квазифункциональный метод (с неявными преобразованиями). –

3

Проблема с start в том, что он не знает истинный тип вашего актера. Таким образом, он возвращает общий. Чтобы обойти это, вам нужен компактный способ его запуска и по-прежнему вернуть действующего актера (а не суперкласса). На самом деле это звучит как полезная возможность вообще, не так ли? - взять объект, заставить что-то сделать, а затем вернуть объект?

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

Теперь вы можете

(new MyActor).effect(_.start) 

и типа будут сохранены. (Если вы не используете Scalaz, такая возможность настолько полезна вообще, что вы можете захотеть поместить ее в свою личную библиотеку с удобными фрагментами кода. Это у меня. У вас есть один, не так ли?)

+0

Ницца. Мне нравится это. Решил что-то, что меня беспокоит довольно долго. Поскольку я новичок в FP в целом, у меня есть некоторые проблемы с обработкой побочных эффектов, особенно в функциональных литералах. –

+0

Очень круто. Я ценю очень полезный совет. Благодаря! –

Смежные вопросы