2013-04-03 61 views
2

我有一些基於Akka的actor系統,其中多種actor是基於相同模板的,這是因爲這些actor只有不同的響應值類型。例如:如何避免在模式匹配警衛中顯式.isDefinedAt()調用

final case class Request(data: Any) 
final case class Response(data: Any) 

abstract class ActorTemplate[T] extends Actor { 
    def dataFunction: PartialFunction[Any, T] 

    def respond(data: T): Response 

    def receive: Receive = { 
    case Request(data) if dataFunction.isDefinedAt(data) => 
     sender ! respond(dataFunction(data)) 
    }  
} 

部分函數有避免類型擦除方法,該方法防止我簡單

def receive: Receive = { 
    case Request(data: T) => 
     sender ! respond(data) 

,並在同一時間強迫我上產生圖案if dataFunction.isDefinedAt(data)防護件和我只是不要我不喜歡它。

有什麼辦法可以避免明顯的防範?

只有這樣我發現現在是介紹一些愚蠢的提取:

object DataExtractor { 
    def unapply(data: Any): Option[T] = 
    if (dataFunction.isDefinedAt(data)) Some(dataFunction(data)) else None 
} 

def receive: Receive = { 
    case Request(DataExtractor(data) => 
    sender ! respond(data) 

但或許它是在標準庫中已經某處做了什麼?或者,也許有其他方法類似於收集collect方法,但匹配?

結論

後的一些想法,我又回到提取物,並用@幫助pagoda_5b建議移動它變成一個特點:

trait PFExtract[T] { 
object PF { 
    def unapply(any: Any)(implicit pf: PartialFunction[Any, T]): Option[T] = 
    pf.lift(any) 
} 
} 
+0

'dataFunction'的類型簽名似乎拼寫錯誤。它應該是'PartialFunction [Any,T]' –

+0

修復它,謝謝。 – Seigert

+0

pagoda_5b有很好的建議,但你的提取器也不錯。 – sourcedelica

回答

3

我實際上做的是使用applyOrElse方法上dataFunction,當沒有爲給定的輸入

def defaultAnswer: T 

def receive: Receive = { 
    case Request(data) => 
    sender ! respond(dataFunction.applyOrElse(data, defaultAnswer)) 
} 

定義的部分功能定義默認響應如果PR EFER來包裝你的答案在Option,已經有一個名爲lift方法,它會替你,你猜對

def receive: Receive = { 
    case Request(data) => 
    sender ! respond(dataFunction.lift(data)) 
} 

你甚至可以決定是否功能沒有進行數據定義不回答

def receive: Receive = { 
    case Request(data) => 
    dataFunction.lift(data).foreach { 
     sender ! respond(_) 
    } 
} 

foreach定義在Option類型上,只有在有一些內容可用時才運行閉包內的代碼(即如果你有一個Some(...)

+0

嗯,這是可能的解決方案, 謝謝!但是: 1.如果我們不想用'None'或'defaultValue'調用'respond',只有第三種解決方案有效; 2.雖然前兩種解決方案提供了一些手段給'發件人'一些關於不適用的數據的反饋,第三種解決方案悄悄地拋出。 然後再次 - 謝謝你,那些是思想的食物。 – Seigert

+0

@Seigert我建議了三種解決方案,因爲從你發佈後我不確定你最喜歡處理「意外數據」的方式。 –