Scala actor kills itself inconsistently

201 views Asked by At

I am a newbie to scala and I am writing scala code to implement pastry protocol. The protocol itself does not matter. There are nodes and each node has a routing table which I want to populate. Here is the part of the code:

def act () {
def getMatchingNode (initialMatch :String) : Int = {
val len = initialMatch.length
  for (i <- 0 to noOfNodes-1) {
    var flag : Int = 1
    for (j <- 0 to len-1) { 
      if (list(i).key.charAt(j) == initialMatch(j)) {
        continue
      } 
      else {
        flag = 0
      }
    }
    if (flag == 1) {
      return i
    }
  }
 return -1
}


// iterate over rows
for (ii <- 0 to rows - 1) {
  for (jj <- 0 to 15) {
    var initialMatch = ""
     for (k <- 0 to ii-1) {
       initialMatch = initialMatch + key.charAt(k)
     }
     initialMatch += jj
     println("initialMatch",initialMatch)
     if (getMatchingNode(initialMatch) != -1) {
       Routing(0)(jj) =  list(getMatchingNode(initialMatch)).key
     }
     else {
       Routing(0)(jj) =  "NULL"
     }
  }
 }

}// act

The problem is when the function call to getMatchingNode takes place then the actor dies suddenly by itself. 'list' is the list of all nodes. (list of node objects) Also this behaviour is not consistent. The call to getMatchingNode should take place 15 times for each actor (for 10 nodes). But while debugging the actor kills itself in the getMatchingNode function call after one call or sometimes after 3-4 calls. The scala library code which gets executed is this :

def run() {
try {
  beginExecution()
  try {
    if (fun eq null)
      handler(msg)
    else
      fun()
  } catch {
    case _: KillActorControl =>
      // do nothing

    case e: Exception if reactor.exceptionHandler.isDefinedAt(e) =>
      reactor.exceptionHandler(e)
  }
  reactor.kill()
}

Eclipse shows that this code has been called from the for loop in the getMatchingNode function

def getMatchingNode (initialMatch :String) : Int =  {
  val len = initialMatch.length
  for (i <- 0 to noOfNodes-1) 

The strange thing is that sometimes the loop behaves normally and sometimes it goes to the scala code which kills the actor.

Any inputs what wrong with the code??

Any help would be appreciated.

2

There are 2 answers

0
Deepti Jain On

Got the error.. The 'continue' clause in the for loop caused the trouble. I thought we could use continue in Scala as we do in C++/Java but it does not seem so. Removing the continue solved the issue.

0
pagoda_5b On

From the book: "Programming in Scala 2ed" by M.Odersky

You may have noticed that there has been no mention of break or continue. Scala leaves out these commands because they do not mesh well with function literals, a feature described in the next chapter. It is clear what continue means inside a while loop, but what would it mean inside a function literal? While Scala supports both imperative and functional styles of programming, in this case it leans slightly towards functional programming in exchange for simplifying the language. Do not worry, though. There are many ways to program without break and continue, and if you take advantage of function literals, those alternatives can often be shorter than the original code.

I really suggest reading the book if you want to learn scala

Your code is based on tons of nested for loops, which can be more often than not be rewritten using the Higher Order Functions available on the most appropriate Collection.

You can rewrite you function like the following [I'm trying to make it approachable for newcomers]:

//works if "list" contains "nodes" with an attribute "node.key: String"
def getMatchingNode (initialMatch :String) : Int = {

  //a new list with the corresponding keys
  val nodeKeys = list.map(node => node.key)

  //zips each key (creates a pair) with the corresponding index in the list and then find a possible match
  val matchOption: Option[(String, Int)] = (nodeKeys.zipWithIndex) find {case (key, index) => key == initialMatch}

  //we convert an eventual result contained in the Option, with the right projection of the pair (which contains the index)
  val idxOption = matchOption map {case (key, index) => index} //now we have an Option[Int] with a possible index

  //returns the content of option if it's full (Some) or a default value of "-1" if there was no match (None). See Option[T] for more details
  idxOption.getOrElse(-1)
}   

The potential to easily transform or operate on the Collection's elements is what makes continues, and for loops in general, less used in Scala

You can convert the row iteration in a similar way, but I would suggest that if you need to work a lot with the collection's indexes, you want to use an IndexedSeq or one of its implementations, like ArrayBuffer.