0

私はscalaの初心者で、ペストリープロトコルを実装するためのscalaコードを書いています。プロトコル自体は問題ではありません。ノードがあり、各ノードには入力したいルーティング テーブルがあります。コードの一部は次のとおりです。

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

問題は、getMatchingNode への関数呼び出しが行われると、アクターが勝手に死んでしまうことです。「リスト」はすべてのノードのリストです。(ノード オブジェクトのリスト) また、この動作には一貫性がありません。getMatchingNode の呼び出しは、各アクター (10 ノード) に対して 15 回行う必要があります。しかし、デバッグ中に、アクターは getMatchingNode 関数を 1 回呼び出した後、または 3 ~ 4 回呼び出した後に自分自身を殺します。実行される scala ライブラリ コードは次のとおりです。

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 は、このコードが getMatchingNode 関数の for ループから呼び出されたことを示しています。

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

奇妙なことに、ループが正常に動作する場合もあれば、アクターを殺す scala コードに移動する場合もあります。

コードの何が問題なのですか??

どんな助けでも大歓迎です。

4

2 に答える 2

0

エラーが発生しました。forループの「continue」句が問題の原因でした。C ++ / Javaの場合と同じように、Scalaでもcontinueを使用できると思いましたが、そうではないようです。続行を削除すると、問題が解決しました。

于 2012-10-21T17:01:50.920 に答える
0

本から:M.Oderskyによる「Scala 2edでのプログラミング」

中断または継続について言及されていないことに気付いたかもしれません。これらのコマンドは、次の章で説明する機能である関数リテラルとうまくかみ合わないため、Scala はこれらのコマンドを除外します。while ループ内で continue が何を意味するかは明らかですが、関数リテラル内では何を意味するのでしょうか? Scala はプログラミングの命令型スタイルと関数型スタイルの両方をサポートしていますが、この場合、言語を単純化する代わりに関数型プログラミングにやや傾いています。しかし、心配しないでください。ブレーク アンド コンティニュなしでプログラミングする方法はたくさんあります。関数リテラルを利用すると、それらの代替手段は多くの場合、元のコードよりも短くなります。

scalaを学びたいなら、本を読むことを本当にお勧めします

あなたのコードは、ネストされた多数のfor ループに基づいています。これは、最も適切なCollectionで利用可能な高次関数を使用して頻繁に書き換えることができます。

次のように関数を書き換えることができます [私は初心者にとって親しみやすいものにしようとしています]:

//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)
}   

Collectionの要素を簡単に変換または操作できる可能性があるため、 continuesfor ループは一般的に Scala ではあまり使用されません。

同様の方法で行の反復を変換できますが、コレクションのインデックスを頻繁に操作する必要がある場合は、IndexedSeqまたはその実装の 1 つ ( ArrayBufferなど) を使用することをお勧めします。

于 2012-10-22T13:32:31.483 に答える