5

外部データストアからの一連のXML応答を解析しています。その間、子ノードの存在をテストし、存在する場合はその値をテストする必要があります。それを達成するために、私は次のコードを持っています:

...
  val properties = for {
    val row <- root \\ "ResultDescription"
    val cond:Boolean = checkDetectionNode(row) match {
      case Some(nodeseq) => {
          val txt = nodeseq.text.toLowerCase
          if (txt contains "non-detect")
            false
          else
            true
      }
      case None => true
    }
    if (cond)
    val name = (row \ "CharacteristicName").text
    if (charNameList.exists(s => s == name) == false)
  } yield {
    getObservedProperty(name) match {
      case Some(property) => {
          charNameList = name :: charNameList
          property
      }
    }
  }
...

checkDetectionNodeは次のように定義されます。

private def checkDetectionNode(row: scala.xml.NodeSeq) : Option[scala.xml.NodeSeq] = {
  if ((row \ "ResultDetectionConditionText") != null)
    Some[scala.xml.NodeSeq]((row \ "ResultDetectionConditionText"))
  else
    None
}

上記のコードでは、行に「単純な式の不正な開始」という不特定のエラーが発生しますval name...。正直なところ、私はScalaプログラマーでも、関数型プログラマーでもありません(常に、OO /命令型に対してより部分的でした)。私はScalaを数日間使用しており、Javaおよびラムダ演算子から知っていることのほとんどに基づいています。残念ながら、私は座って、Scalaを本当に学ぶ時間がありません。締め切り、私たち全員を馬鹿にします。

私は誰かが見て、私が間違っていることがあるかどうか私に知らせてくれることを望んでいます(私は確かにそうです)。表示されるコードを、質問に関連するものに制限しようとしました。ただし、追加のコードが必要な場合はお知らせください。

ありがとう

4

3 に答える 3

3

まず第一に、その名前の子が存在しない場合はそうで(row \ "ResultDetectionConditionText")はないことに注意してくださいnull— それは単に空になりますNodeSeq(慣用的な Scala コードは を返すことを避ける傾向がありnullます。おそらくお気付きでしょう)。したがって、現在のコードは常に を返しますがSome、これはおそらくあなたが望むものではありません。に変更する!= null.nonEmpty、その問題が解決します。

次に、条件付きロジックをより簡潔に記述する方法を次に示します。

val cond = (row \ "ResultDetectionConditionText").exists(
  _.text.toLowerCase contains "non-detect"
)

これは、NodeSeqという名前のすべての子を含む を取得し"Result..."、存在する場合はそれを取得しNodeSeq、テキスト を含むノードをチェックすることを意味します"non-detect"。ノードのテキストを個別にチェックするため、ロジックはあなたのものとまったく同じではありませんが、実際には、あなたの意図がさらに優れていると私が推測するものに適合します。おそらく、このようなものをテストに合格させたくないでしょう。

val row = <row>
  <ResultDetectionConditionText>non-d</ResultDetectionConditionText>
  <ResultDetectionConditionText>etect</ResultDetectionConditionText>
</row>

ただし、現在のバージョンではそうなります。

しかし、これで"illegal start of simple expression"問題が解決するわけではありません。ロジックを修正し、16 行のコードを 3 行に削減するだけです。ここでの問題は、name行ったばかりのテストが失敗した場合にどうあるべきかを決定する必要があることです。最も明白なアプローチは、次を使用することOptionです。

val name = if (cond) Some((row \ "CharacteristicName").text) else None

ただし、 の使用方法によってはname、他のアプローチがより適切な場合があります。

于 2012-09-06T21:17:47.323 に答える
1

xml はここで気を散らすものです。問題は、末尾の if (cond) がガードとして機能していないことです。本来あるべきように見えます。コンパイラは、新しい if 'then' 部分の開始と見なします。

次の例では:

val l = List(1,2,3,4,5)

val r = for {
    i <- l 
      if (i > 2)
    x <- Some(i * 2)
  } yield x

ご想像のとおり、 List(6,8,10) が得られます。

使用する

val r = for {
    val i <- l if (i > 2)
    val x <- Some(i * 2)
  } yield x

非推奨の警告が表示されるはずです。

val r = for {
    val i <- l 
    if (i > 2)
    val x <- Some(i * 2)
  } yield x

取得

error: illegal start of simple expression
  val x <- Some(i * 2)

Generator (Pattern1 '<-' Expr [Guard]) の前にある val を削除するだけで、通常のサービスを再開できます。また、私が見つけた for ループに vals がないと、もう少しうまく流れます。

于 2012-09-07T22:23:34.300 に答える
0

if (cond)式の後に式を続ける必要があります。Scalaではif、Javaの三項演算子に似ています。これは式であり、ステートメントではありません。val変数宣言は(Javaのように)式ではないため、ifのthen一部にを含めることはできません。

正直なところ、私はあなたがそこで何を達成したいのか推測できないので、意味のある構文的に正しい代替案を提案することはできません。ただし、に依存するロジックがさらにある場合はcond、それをブロックに入れることができます。

if (cond) {
  val name = ...
  // do more here
}
于 2012-09-06T21:05:32.173 に答える