views:

355

answers:

1

There are plenty of examples of actors replying with another message back to the sender, but whilst browsing the API docs I noticed the !! and !? operators which are part of the CanReply trait (which seems to be new to 2.8: http://www.scala-lang.org/archives/rc-api/scala/actors/CanReply.html). I was therefore wondering whether it was just a case of having the receive/react block return a value, i.e. make the PartialFunction return type something other than Unit?

I'll start digging through the source to try to work out how they're meant to be used, but if anyone has any insight or knows of any more in-depth documentation or examples then I'd be most grateful.

Cheers, Paul.

+7  A: 

Replies can be sent with the method reply, as shown here:

import scala.actors._
class Reverser extends Actor {
  def act() { Actor.loop { react {
    case s: String => Thread.sleep(1000); reply(s.reverse)
    case _ => exit()
  }}}
}

There are three ways to explicitly accept the reply.

  • Use !!, which returns a Future, which is a container class that promises to give you the contents when you need them. It returns immediately, but if you actually ask for the contents, you have to wait until the other thread is done and fills the request.
  • Use !? without a timeout. Your code will pause for as long as it takes for the other thread to reply.
  • Use !? with a timeout. Your code will pause until it gets a reply or until the timeout expires, whichever comes first.

Here's an example of all three:

val r = new Reverser
r.start
val a = (r !! "Hi")
a() match {
  case s: String => println(s)
  case _ => println("Error A")
}
val b = r !? "Hello"
b match {
  case s: String => println(s)
  case _ => println("Error B")
}
val c = (r !? (500,"Howdy"))
c match {
  case Some(s: String) => println(s)
  case Some(_) => println("Error C")
  case None => println("Too slow!")
}
r ! None  // None isn't a string, so r will stop running

And if you run this you get

iH
elloH
Too slow!
Rex Kerr
Thanks for that! I also did a bit of searching myself and found this:http://java.dzone.com/articles/scala-threadless-concurrentwhich by the date of it suggests that the operators are not new to 2.8, even if the CanReply trait is.
pdbartlett
@pdbartlett: That's correct. The code above will work in 2.7 also, except that `.reverse` doesn't produce a string in 2.7, so the example won't work unless you do `.reverse.toString`. But all the actor/future stuff works just fine.
Rex Kerr