Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercept / Decorate a PartialFunction

Tags:

scala

How do I intercept a PartialFunction? e.g. in actors, if I'd like to just print everything that comes into the following receive method before passing it onto the process method:

class MyActor extends Actor {
  def receive : Receive = process
  def process : Receive = {
    case Some(x) => /* do one thing */ ()
    case None => /* do another thing */ ()
    case _ => /* do something else */ ()
  }
}
like image 392
Jamie McCrindle Avatar asked Dec 16 '13 23:12

Jamie McCrindle


3 Answers

A PartialFunction is a trait that you can implement. You aren't forced to use the case syntax.

Unfortunately, it doesn't come with a convenient method for composing in the way you describe. The closest is the andThen method, but the argument you pass must be a regular function, which could lead to match errors when an argument is unhandled in the actual receive function. So you're stuck writing it the long way.

class MessageInterceptor(receiver: Receive) extends Receive {
  def apply(msg: Any) = {
    /* do whatever things here */
    receiver.apply(msg)
  }
  def isDefinedAt(msg: Any) = receiver.isDefinedAt(msg)
}

val process = new MessageInterceptor(receive)
like image 159
Dylan Avatar answered Oct 21 '22 08:10

Dylan


def process: Receive = printMessage andThen {
  case Some(x) => /* do one thing */ ()
  case None => /* do another thing */ ()
  case _ => /* do something else */ ()
}

def printMessage: PartialFunction[Any, Any] = {
  case m => 
    println(m)
    m
}
like image 36
vptheron Avatar answered Oct 21 '22 08:10

vptheron


I suppose andThen method is a right choice:

def printEverything: PartialFunction[Any, Any] = {
case x =>
    println(x)
    x
}

and use it:

def receive : Receive = printEverything andThen process
like image 2
maks Avatar answered Oct 21 '22 10:10

maks