Pregunta

I'm currently studying Scala & Akka and developing test application for it. In this application almost all actors log unhandled messages for ease of debug:

import akka.actor._

class TestActor extends Actor with ActorLogging {
  def receive: Receive = {
    case Some(value) => // do something...
    case msg => log.debug("Unhandled message: {}.", msg)
  }
}

As I said, such code exists almost in all of my agents and I started to think about moving it into a trait:

trait LogUnhandled { this: Actor with ActorLogging =>
  def logUnhandled: Receive = {
    case msg => log.debug("Unhandled message: {}.", msg)
  }
}

and using it after like

class TestActor extends Actor with ActorLogging with LogUnhandled {
  def receive: Receive = {
    case Some(value) => // do something...
  } orElse logUnhandled
}

I was wondering mostly if structural subtyping will allow me do that or TestActor#Receive and LogUnhadled#Receive would be different types, but even before that I've got

error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?

And for now I could not figure how to avoid this other than by moving first {...} block into separate function:

class TestActor extends Actor with ActorLogging with LogUnhandled {
  def doReceive: Receive = {
    case Some(value) => // do something...
  } 

  def receive: Receive = doReceive orElse logUnhandled
}

Latter will do, of course, but it is kinda 'missing the point' and inflicts some other side effects like 'think about appropriate function name instead of receive'...

So I wonder: is it possible to avoid 'missing type parameter error' by somehow declaring (Any) => Unit function signature 'in place'?

¿Fue útil?

Solución

class TestActor extends Actor with ActorLogging with LogUnhandled {
  def receive = ({
    case Some(value) => // do something...
  }: Receive) orElse logUnhandled
}

Also take a look at this. LoggingReceive lets you do sth like the following:

class A extends Actor {
   def receive = LoggingReceive {
      case msg => ...
   }
}

And all accepted/rejected messages are going to be published to the debug stream.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top