Domanda

I am beginner in akka and I am stuck in this compilation problem :

class MyActor extends Actor {
  def receive = {
    case Outer(operation, someInt, someBool) =>
      makeOperation(operation, someInt, someBool) 
  }    

  private def makeOperation(operation: Operation, someInt: Int, someBool: Boolean): Receive = {
    operation match {
      case MainOp(otherInt) =>
        if (someBool) {
          if (otherInt < someInt) {
            root ! makeMessage(...)
          } else if (otherInt > someInt) {
            root ! makeMessage(...) // <-  compilation error here
          } else {
            root ! makeMessage(...) // <-  compilation error here
          }
        } else {
          if (otherInt > someInt) {
            root ! makeMessage(...) // <-  compilation error here
          } else if (otherInt < someInt) {
            root ! makeMessage(...) // <-  compilation error here
          } else {
            root ! makeMessage(...) // <-  compilation error here
          }
        }
      case OtherOp1(...) => ???
      case OtherOp2(...) => ???
    }
  }
}

Here the error the console displays :

MyFile.scala:161: type mismatch;
  found   : Unit
  required: MyActor.this.Receive
     (which expands to)  PartialFunction[Any,Unit]
             root ! makeMessage(...)
                  ^
 6 errors found
(assignment/compile:compile) Compilation failed
[error] Total time: 108 s, completed Dec 19, 2013 9:07:46 PM

How can I solve this problem?

È stato utile?

Soluzione

Short answer

Replace this line:

private def makeOperation(...): Receive = {

With this:

private def makeOperation(...): Unit = {

Result type of your expression operation match { ... } is Unit, since it's the result type of the last method (!) in every brunch.

Details

Method makeOperation is wrong named. What it really do is processing messages.

Actually you don't need this method at all - you could process messages in normal like this:

val normal: Receive = {
  case Outer(MainOp(otherInt), someInt, true)
    if otherInt < someInt => root ! makeMessage(...)
  case Outer(MainOp(otherInt), someInt, true)
    if otherInt > someInt => ...
  case Outer(MainOp(otherInt), someInt, true) => ...
  case Outer(MainOp(otherInt), someInt, false)
    if otherInt < someInt => ...
  case Outer(MainOp(otherInt), someInt, false)
    if otherInt > someInt => ...
  case Outer(MainOp(otherInt), someInt, false) => ...
  case Outer(OtherOp1(...), someInt, someBool) => ...
  case Outer(OtherOp2(...), someInt, someBool) => ...
}

You'd need a method with result type Receive only if you want to change actor's behavior for next message (and all messages after) like this:

context become createNewBehavior(params)

See these answers for examples:

Initializing an actor before being able to handle some other messages

How to properly use akka actors in scala

Is it possible to do that in Scala (without mutating the internal state of a class)?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top