[英]Scala pass function args through to case class copy constructor?
我有一些(Akka)演員代碼,使用案例類+復制構造函數來更新狀態:
def foo(state:StateCaseClass) : Receive = {
import state._
{
case Bar(updates) =>
context become foo(copy(/* change a limited number of things */))
// ... other message processing w/ lots of context become foo(copy(...))
}
}
我想在導入下方添加
def update = context become foo(copy(_))
這樣代碼可以是
def foo(state:StateCaseClass) : Receive = {
import state._
def update = context become foo(copy(_))
{
case Bar(updates) =>
update(/* change a limited number of things */)
// ... etc
}
}
但這不能編譯。 我當然可以稍微調整一下def update
以擺脫大多數樣板,但是copy
仍然存在:
def foo(state:StateCaseClass) : Receive = {
import state._
def update(newState:StateCaseClass) = context become foo(newState)
{
case Bar(updates) =>
update(copy(/* change a limited number of things */))
// ... etc
}
}
是否有可比的語法使我可以通過args傳遞到case類副本構造函數並耗盡最后一點?
免責聲明 :我猜最好的解決方案是使用context become
顯式。 而且我不建議您使用下面的代碼。
我想沒有元編程(宏)是不可能的。 您必須為命名參數創建具有默認值的方法。
您總是可以像這樣手動創建此類方法:
def update(filed1: Int = state.field1, field2: String = state.field2) =
context become foo(StateCaseClass(filed1, filed2))
...
update(field1 = 0)
...
update(field2 = "str")
但我想這不是您想要的。
無需元編程即可獲取此類方法的唯一方法是...使用方法copy
本身。 方法copy
調用構造函數,您可以調用become
構造函數。
下面的代碼有效,但我強烈建議您不要使用它! 這是一個密碼,它將使所有其他開發人員感到困惑。
import akka.actor._
trait ReceiveHelper extends PartialFunction[Any, Unit] {
def receive: PartialFunction[Any, Unit]
override def apply(v: Any) = receive(v)
override def isDefinedAt(v: Any) = receive isDefinedAt v
}
sealed trait TestActorMessage
case object Get extends TestActorMessage
case class SetInt(i: Int) extends TestActorMessage
case class SetString(s: String) extends TestActorMessage
class TestActor extends Actor {
case class Behaviour(intField: Int, strField: String) extends ReceiveHelper {
context become this
val receive: Receive = {
case Get => sender ! (intField -> strField)
case SetInt(i) => copy(intField = i)
case SetString(s) => copy(strField = s)
}
}
def receive = Behaviour(0, "init")
}
用法:
val system = ActorSystem("testSystem")
val testActor = system.actorOf(Props[TestActor], "testActor")
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
implicit val timeout = Timeout(5 seconds)
testActor ? Get foreach println
// (0,init)
testActor ! SetInt(666)
testActor ? Get foreach println
// (666,init)
testActor ! SetString("next")
testActor ? Get foreach println
// (666,next)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.