Given an instance of a behavior can I apply a message to it to create a new behavior

61 views Asked by At

I have a scenario where I am handling a generic Behavior that needs some extra information when a message is received:

case class A(count: Int)

type MyBehavior[T] = Behavior[(A, T)]

The code to handle this extra information might be something like the following:

case class B(str: String)

def active(b: B): MyBehavior[B] = Behaviors.receiveMessage {
  case (a, b) =>
    active(b.copy(str = a.count.toString)
}

I then have a function to handle this Behavior generically. But given a reference to a behavior, I don't know how to apply a message to it to create a new behavior:

def f[T](a: A, behavior: MyBehavior[T])(implicit ct: ClassTag[T]): Behavior[T] =
    Behaviors.receiveMessage {
        case t: T =>
            val newBehavior: MyBehavior[T] = ???   // Can I pass a and t?
            f(a.copy(count = a.count + 1), newBehavior)
}

Is there a way for me to apply a message to a behavior to create a new behavior?

1

There are 1 answers

1
Mateusz Kubuszok On BEST ANSWER

You can spawn a new actor using context and send a message to if from your current actor. This way you can "prepend" some logic before action done by that actor.

Behaviors.setup { context =>

  def f[T](implicit ct: ClassTag[T]): Behavior[(A, T)] =
    Behaviors.receiveMessage {
      case (a: A, t: T) =>
        val newA = a.copy(count = a.count + 1)
        val newActor = context.spawn(f[T])
        newActor ! (newA, t)
    }
}

Important thing that is missing from your code - behavior is a recipe for an actor, but it is not an actor on its own. You have to instantiate it using ActorSystem(behavior, actorSystemName) (entry to whole system) or via context.spawn(behavior). Without that you recursive calls will be just recursive calls, not sending a message from actor to a newly spawned actor.