2013-12-15 68 views
0

我有2个角色处理消息,男演员发送消息到演员B.演员B,则应该处理这些数字并打印在同一行与演员

我的代码:

class ActorB extends Actor{ 
    def receive = { 
    case 0 => println("0") 
    case x : Int => println (x) 
    } 
} 

但韩元“T编译

+0

如果你打算让你的actor有状态,为什么不把消息存储在本地列表中,然后在你的列表包含3个项目时将它们打印出来呢? – Felix

+0

我加了一个答案。有状态意味着你的价值(你的演员)会随着“时间”的流逝而表现出不同,也就是说,如果你使用成为/不成熟,你的演员每次收到一条消息都不会执行相同的动作。在下面的回答中,您将有状态限制在您的演员所包含的列表中,查看接收情况,它会更清晰地发生什么,因为我们以可读的方式处理列表的状态。 – Felix

回答

1

你可以做这样的事情(没有经过测试):

class ActorB extends Actor with ActorLogging { 

    def receive = { 
    case x : Int => context.become(waitingForMore(List(x))) 
    } 

    def waitingForMore(xs : List[Int]) : Receive = { 
    case x : Int if(xs.size == 2) => 
     printResults(x :: xs) 
     context.become(receive) 

    case x : Int => context.become(waitingForMore(x :: xs))  
    } 

    def printResults(xs : List[Int]): Unit = { 
    // Do printing here. 
    } 
} 

在这种模式下,你将采取的事实,演员可以改变自己的内部行为的优势。你不会明确地存储一个Ints列表,而是你将从一个函数传递给另一个函数。本质上,演员等待你发送一个Int(receive方法),然后进入收集更多结果的状态(waitingForMore方法)。一旦该方法收集到足够的数据,它将打印结果并返回到receive方法中,该方法将重新开始整个过程​​。

编辑正如所建议的,我只是添加一个小的评论,为什么我提出这个模型。我觉得你的演员所处的状态更清晰地模拟了这一点。随着问题的增加和变得越来越复杂,这可能是一个很好的模式。或者它可能不会,因为费利克斯指出这两种解决方案通过不同的方式得到相同的答案。您绝对应该随时挑选您感觉更舒适的解决方案。我的目的是展示一个更实用的替代方法,就是这些。

+1

问题恕我直言,我们似乎没有得到任何东西在这里相比,我的解决方案。由于我们正在改变“接收”的实施方式,因此它没有更多的功能。阅读也不容易。也许你可以详细说明何时使用它而不是在内部显式管理状态? – Felix

+0

同意这两个实现在一天结束时达到相同的结果。考虑到这一点,OP应该选择他/她认为将为他们完成工作的人。我不确定我是否会以这种方式实现它(我可能会明确地模拟状态,因为你有它),但我只是提出了一个我以前见过的替代解决方案。 – Todd

2

你可以做这样的事情:

class ActorB extends Actor with ActorLogging{ 
    var xs:List[Int] = Nil 
    def receive = { 
    case x : Int => 
     xs = x :: xs 
     if(xs.length==3){ 
      println(xs.mkString(" ")+" avg: "+xs.sum/3d) 
      xs = Nil 
     } 
    } 
} 

(我没有测试以上,b它应该给你的想法)

我认为这可能比使用成为/ unbecome更容易一点。也许你有理由使用这种模式?

+0

我现在没有安装Scala的计算机,但我认为你应该可以自己调试它:) – Felix

+0

您可以在打印时将其颠倒过来,例如: println(xs.reverse.mkString(“”)+“avg:”+ xs.sum/3d)。逻辑很简单。您将每条消息保存到列表'xs'的前面。如果在保存当前元素之后,列表的大小为3,则只需将其打印出来并将xs定义为新的空列表。 – Felix