Passing collections in scala actors - scala

When I need to pass typed collections to an actor, I get an "unchecked" warning in my react method:
val actor = actor {
loop {
react {
case a:List[String] => // do something
}
}
}
How can I work around this? I tried boxing collection in a separate class (but that is ugly and cumbersome), and just casting collection (case a:List[_] => a.asInstanceOf[List[String]]) after receiving it by actor is not type-safe and dangerous.

Because the JVM does not keep track of the type of generics, you can't know that a List[_] is a List[String] unless you examine every element and check that it is a string. Your best bet is in fact to box the collection in a separate class. It need not be so bad!
case class StringsBox(ls: List[String]) {}
//...
myactor ! StringsBox( List("these","are","strings") )
//...
react {
case StringsBox(ls) => /* Now you have your List[String] */
}

Related

How to avoid mutating of a state variable in an Akka actor with inherited behavior?

I have some Akka actors with a common behavior. This common behavior is defined in a trait:
trait CommonBehavior {
this: Actor =>
var history: List[String] = Nil
protected def commonActions: Receive = {
case Action1 => history = "action1" :: history.take(99)
case Action2 => history = "action2" :: history.take(99)
case GetHistory => sender() ! history
}
}
The actors override this trait and define additional behavior with orElse. This is one example of such actor:
class MyActor extends Actor with CommonBehavior {
var state: Int = 0
override def receive: Receive =
commonActions orElse {
case Increment => state += 1
case Decrement => state -= 1
}
}
I know that mutating the state is an antipattern and I want to refactor it with the usage of context.become. The problem is, when changing state in MyActor with context.become, I do not know the parameter for commonActions. Is it even possible to inherit behavior? Do I need a bigger refactor (e.g. creating a proxy actor)? This is how far I have got:
trait CommonBehavior {
this: Actor =>
protected def commonActions(history: List[String]): Receive = {
case Action1 => context.become(??? orElse commonActions("action1" :: history.take(99))
case Action2 => context.become(??? orElse commonActions("action2" :: history.take(99))
case GetHistory => sender() ! history
}
}
class MyActor extends Actor with CommonBehavior {
override def receive = ready(0)
def ready(state: Int): Receive = {
case Increment => context.become(ready(state + 1) orElse commonActions(???))
case Decrement => context.become(ready(state - 1) orElse commonActions(???))
} orElse commonActions(Nil)
}
Mutating state in an actor is not an antipattern, it is fine to do more OO style actors (and can in high througput cases be more performant) which mutate state in response to messages. Deciding to do a more FP-style is a personal preference so consider the pros and cons for your use case (your experience, team experience, project size, etc) rather than follow someones opinion dogmatically. Especially if you already have a class hierarchy that expects you to do mutations rather than switch behaviors.
If you decide you want to do a more FP-style actor, I'd recommend reconsidering the whole structure and not have a mixin with mutable state, requiring to be mixed in with an Actor to start with but design from that point of view. I'd also recommend going with the new typed APIs as the "FP:y" side of those gives a much nicer experience than using become with the classic Actor APIs.
As I understood, you want to avoid state mutation within actor by changing the context of the actor. So, there are 2 possibilities:
If you are afraid to mutate the state within the actor, you can go with that as the mutation within the actor is fine and does not lead to concurrency issues. Its because actors work synchronously.
If you still want to keep the state immutable (val) and allow changing the state on runtime, you can do that using become. If you don't know the parameters for commonActions, you can either initialize it with a default value or pick the value from storage depending on business logic and then update accordingly.

Scala: How to extend an Akka actor?

I wrote an Akka base-actor that can handle some common messages. I want to reuse this basic behavior in a sub-actor, by extending the base-actor (not by composition of the base-actor).
I have seen several approaches in previous questions. They are all valid but also may be improved:
How extend behaviour of super actor in akka
and
How do I best share behavior among Akka actors?
To make the implementation cleaner, I am trying to achieve the following:
When defining the sub-actor, I try to extend only the base-actor (not both Actor and sub-actor). However, I was not able to force the compiler to do this.
I also try to not rename the receive partial function, because it is a kind of convention.
Here is a sample of my implementation:
//This is the base-actor that implements the common behavior
trait BetterActor extends Actor {
abstract override def receive = {
super.receive orElse { case _ => println("Missing pattern!") }
}
}
//This is the actor that implements the additional behavior.
//I actually wanted to extend BetterActor. It was not possible.
class MyActor extends Actor {
def receive = {
case i: Int =>
println(s"Yay!!! Got $i")
}
}
Here are two alternative ways how I can create an instance of the sub-actor, which combines both the common and the additional behaviors:
//1.
val myBetterActor = system.actorOf(Props(new MyActor with BetterActor), "myBetterActor")
//2.
class MyBetterActor extends MyActor with BetterActor
val myBetterActor = system.actorOf(Props[MyBetterActor], "myBetterActor")
Finally, I may invoke the sub-actor by:
myBetterActor ! 2
myBetterActor ! "a"
Problems with my implementation:
When I create an instance of the sub-actor, only then I can mix in the base-actor, either directly (1) or by defining a new class that mixes in the base-actor.
Like I said before, I would prefer to mix in the base-actor when I define the sub-actor. Not when I try to create an instance of the sub-actor.
P.S. It's fascinating that the designers of this framework did not see it necessary to make this common requirement easy to accomplish.
i suppose as long as you're not trying to override behavior with BetterActor, you could try something like this:
trait BetterActor extends Actor {
override def unhandled(message: Any): Unit = message match {
case e: CommonMessage => println("COMMON!")
case e => super.unhandled(e)
}
}
class MyActor extends BetterActor {
override def receive = {
case i: Int => println(s"Yay!!! Got $i")
}
}

Using 'nested' types in a list in Scala

I'm using ScalaFX and JavaFX, and have this code:
import scalafx.Includes._
class Type1(anInt: Int, ...)
class Type2(aString: String, ...)
class ListItem[T](internalValue:T, ...)
object Worker
{
val list1 = FXCollections.observableArrayList[ListItem[Type1]]()
val list2 = FXCollections.observableArrayList[ListItem[Type2]]()
def workWithList(list:ObservableList[ListItemType]) {
list.foreach(i => workWithItem(i))
}
def workWithItem(item:ListItem) {
item match {
case i:ListItem[Type1] => do something
case i:ListItem[Type2] => do something else
}
}
workWithList(list1)
workWithList(list2)
}
My problem is that this code doesn't compile; it says that I can't use ObservableList[ListItem[Type1]] for the workWithList method, which expects ObservableList[ListItem].
As I've been playing with this, some variations of this code says that there are unchecked warnings, and that pattern matching won't work due to type erasure.
Ideally:
there would be just a single list that could hold objects of type ListItem[Type1] and ListItem[Type2]
I could do pattern matching when working with the items to do different things depending on what kind of item is being worked with
workWithItem could work with either type of item. In my current code I've had to change the signature to workWithItem(item:ListItem[_]) and then do workWithItem(someItem.asInstanceOf[ListItem[_]]). Probably not the correct thing to do!
Thanks!
The method signature for workWithList looks wrong - where does the ListItemType type come from? Should this be def workWithList(list: ObservableList[ListItem[_]]) { ...?
If so, then the problem you will run up against in the match cases is that due to type erasure, the JVM can't tell the difference at runtime between the type signatures of the cases. This can be worked around by, for example, turning the Type1, Type2 and ListItem into case classes (or manually generating unapply methods for them), then deconstructing the item in the match cases, like so:
case class Type1(anInt: Int)
case class Type2(aString: String)
case class ListItem[T](internalValue:T)
object Worker
{
val list1 = FXCollections.observableArrayList[ListItem[Type1]]()
val list2 = FXCollections.observableArrayList[ListItem[Type2]]()
def workWithList(list: ObservableList[ListItem[_]]) {
list.foreach(i => workWithItem(i))
}
def workWithItem(item: ListItem[_]) {
item match {
case ListItem(i: Type1) => println(s"Have type 1: ${i.anInt}") //do something
case ListItem(i: Type2) => println(s"Have type 2: ${i.aString}") //do something else
case anythingElse => println(s"Unknown type: $anythingElse") //just as a safe default for now
}
}
workWithList(list1)
workWithList(list2)
}
Note that I am working here without specific knowledge of the FX libraries (I tried this using straight scala Lists rather than ObservableList or FXCollections.observableArrayList), so they may affect the applicability of this solution (and might be where ListItemType is defined).
The method signature for workWithItem is fine, but the asInstanceOf cast you tried shouldn't be required.
You are attacking mosquito with a shotgun. This example can be solved without parametric polymorphism, with plain old inheritance:
import scalafx.Includes._
import javafx.collections.{FXCollections,ObservableList}
class ListItemType
class Type1(anInt: Int) extends ListItemType
class Type2(aString: String) extends ListItemType
class ListItem(val internalValue:ListItemType)
object Worker
{
val list1 = FXCollections.observableArrayList[ListItem]()
val list2 = FXCollections.observableArrayList[ListItem]()
def workWithList(list:ObservableList[ListItem]) {
list.foreach(i => workWithItem(i))
}
def workWithItem(item:ListItem) {
item.internalValue match {
case i:Type1 => println("do something")
case i:Type2 => println("do something else")
}
}
workWithList(list1)
workWithList(list2)
}
No errors, no warnings, and you can mix both types of objects in the same list.

How can we override the react construct of scala actors?

The usual way of detecting the type of message received in scala actors is by
loop{
react{
case x: String =>
}
}
However, I want to know how can we override this implementation of react construct so that we can do implicit logging of the message that is received.
I am trying to implement a use case mentioned below ->
1. Before a message is matched to any case class, I want to write a log statement on console / file showing the occurance of the message.
2. We can log these messages explicitly by println() / log4j logging . However, I want to design a generic logger for scala actors which will log all the messages sent or received.
Any help in this regard will be helpful.
Thanks in advance
First, be aware that the Scala actors library is being deprecated in favor of Akka. So this answer won't be helpful very long (though the other actors library will continue to be available for a while--and since it's open source potentially forever if people want to maintain it).
Anyway, the react method is defined in scala.actors.Actor. Simply fail to import it, or hide it with your own. Your own what?
Well, the method just takes a PartialFunction[Any,Unit]. So, your should also:
def react(pf: PartialFunction[Any,Unit]): Nothing = { /*how?;*/ Actor.react(/*what?*/) }
You really only have access to the partial function, and you have to defer to Actor.react to do what you want. So you need to wrap pf in another PartialFunction that performs your logging. So you can
val qf = new PartialFunction[Any,Unit] {
def isDefinedAt(a: Any) = pf.isDefinedAt(a)
def apply(a: Any): Unit = {
log(a) // Maybe add more logic to know what a is
pf(a)
}
}
If you want to see messages that come in and get examined but are not actually consumed, you could do more with isDefinedAt also.
So, obviously enough, I hope, /*how?*/ is the above to define (create) qf, and /*what?*/ is just qf.
If you want to know whether a is a case class, the answer is that you cannot (by design). A case class is just syntactic sugar on top of ordinary Scala features; it's just there to save you typing. See, for instance, this question.
However, you can get pretty close by pattern matching for Product and checking whether it has a copy method:
case class M(i: Int)
val a: Any = M(5)
scala> a match {
case p: Product if p.getClass.getMethods.exists(_.getName=="copy") => println("Yes")
case _ => println("No")
}
Yes
If you really want to get fancy, check if copy has the same number and type of parameters as the constructor.
//Following is a code for a logReact Method that does the same thing as react but also logs the message received hope this works for you
import scala.actors.Actor;
import scala.actors.Actor._
trait ActorLogging extends Actor {
def logReact(handler: PartialFunction[Any, Unit]): Nothing = {
val handler2: PartialFunction[Any, Unit] = {
case x =>
println("Inside Logs -- with message recieved -- " + x.toString);
handler.apply(x);
}
super.react(handler2)
}
}
class sumAct extends Actor with ActorLogging {
def act() {
loop {
logReact {
case a: Int =>
println("Inside actor Sum Act Received the message -- " + a)
exit;
}
}
}
}
object ActorLog {
def main(args: Array[String]): Unit = {
var s: sumAct = new sumAct;
s.start();
s ! 1.toInt;
}
}

Scala Actors Send Message to Super Class

I'm trying to make a base class that uses actors, kind of like so:
import scala.actors.Actor
case class FooBar()
class ParentActor extends Actor {
def act {
loop {
react {
case f: FooBar =>
println("Parent Foo")
case _ =>
println("Parent something")
}
}
}
}
And then I want a child class to look like so:
class ChildActor extends ParentActor {
override def act {
loop {
react {
case i: Integer =>
println("Child int")
case default =>
println("Child Base")
super ! default
}
}
}
}
My end goal is to provide a base functionality in the parent actor class that will be executed if the child actor does not react to that case class. I tried doing
super ! Message
But that throws an error:
'.' expected but identifier found.
How can I pass a message from the ChildActor to the base ParentActor act function?
The code which processes the received messages is the PartialFunction which is passed to the react method - in other words it's that case block/closure. It's not possible to call directly any closures which are declared inside other methods (including the superclass' methods), unless that method somehow passes you a reference to the closure instance. And anyways code reuse through inheritance should be avoided.
Since a case block is a PartialFunction, it's possible to compose multiple such blocks using the orElse method. That way you can combine multiple case blocks so that it will fall back to the next one if there is no match for a message.
You don't need inheritance to compose the handlers - just expose the "parent handler" somewhere as a function and compose them before calling react. Or to reduce the boilerplate and make ChildActor unaware of the code in the parent, override the react method in the ParentActor and do the composing of the handlers there before passing it to super.react.