2013-12-15 47 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