2012-09-06 9 views
5

Sto analizzando una serie di risposte XML da un archivio dati esterno. Durante il quale devo testare l'esistenza di un nodo figlio e - se esiste - testarne il valore. Per conseguire aver il codice seguente:Scala XML: test per esistenza nodo e valore

... 
    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 è definito come tale:

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

I risultati di codice di cui sopra in un errore non specificato di "inizio illegale di semplice espressione" sulla linea val name.... Ad essere onesti, non sono un programmatore di Scala o anche un programmatore funzionale (era sempre più parziale a OO/imperativo). Ho usato Scala solo da pochi giorni e ho basato la maggior parte di ciò che conosco dagli operatori Java e lambda. Sfortunatamente, non ho il tempo di sedermi e imparare davvero Scala come vorrei. Scadenze, prendi in giro tutti noi.

Spero che qualcuno possa dare un'occhiata e farmi sapere se c'è qualcosa che sto sbagliando (come sono sicuro che ci sia). Ho provato a limitare il codice mostrato a, quello che spero, è pertinente alla domanda. Tuttavia, mi faccia sapere se è necessario un codice aggiuntivo.

Grazie

+0

Immagino che dovrei chiarire che quanto sopra è parte di una comprensione per affermazione. Il 'if (cond)' è supposto essere per determinare l'esecuzione del blocco di rendimento. Ho modificato la mia risposta per approfondire il codice. – Cowan

risposta

1

L'xml è una distrazione qui. Il problema è che if (cond) alla fine non agisce come una guardia, sembra proprio come dovrebbe, il compilatore pensa che sia l'inizio di una nuova parte se 'poi'.

Nel seguente esempio:

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

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

si otterrà Lista (6,8,10), come ci si potrebbe aspettare.

Utilizzando

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

dovrebbe ottenere un avvertimento deprecazione e

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

ottiene

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

Basta rimuovere la val di fronte al vostro Generator (Pattern1 '< -' Expr [Guard]), e puoi riprendere il normale servizio. Inoltre scorre un po 'più bene senza i vals nel ciclo for che trovo.

+0

Questa è la migliore risposta relativa direttamente alla domanda. Sfortunatamente, questo mi ha fatto ripensare il problema e fare una significativa riscrittura. – Cowan

0

if (cond) devono essere seguiti da un'espressione. In Scala, if è più simile all'operatore ternario in Java: è un'espressione, non un'istruzione. Una dichiarazione di variabile non è un'espressione (come in Java), quindi non è possibile avere un val nella parte then di un if.

Onestamente, non posso indovinare cosa si vuole ottenere lì, quindi non posso suggerire un'alternativa sintatticamente corretta che abbia senso. Ma se avete più logica che dipende cond, si potrebbe mettere in un blocco:

if (cond) { 
    val name = ... 
    // do more here 
} 
+0

Grazie per la risposta concisa. Ho dimenticato che l'istruzione if può fungere da operatore condizionale. Tuttavia, in questo caso sto usando la dichiarazione if come parte di un comprehensive for operation, che a mio avviso (potrei benissimo essere errata) la modifica da un operatore ternario a un requisito condizionale per la dichiarazione di rendimento. Ho rivisto la mia domanda sopra per includere più del codice. – Cowan

3

Prima di tutto, si noti che (row \ "ResultDetectionConditionText") non sarà null se non i bambini con quel nome esiste, sarà solo un vuoto NodeSeq (codice Scala idiomatico tende a evitare di restituire null, come probabilmente avete notato). Quindi il tuo codice attuale restituirà sempre un Some, che probabilmente non è quello che vuoi. La modifica di != null in .nonEmpty risolverà il problema.

Avanti, ecco un modo più conciso di scrivere la vostra logica condizionale:

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

Questo dice: ottenere un NodeSeq che contiene tutti i bambini nome "Result...", se esistono, e quindi verificare che NodeSeq per un nodo che contiene il testo "non-detect". La logica non è esattamente uguale alla tua, dal momento che controlliamo singolarmente il testo dei nodi, ma in realtà si adatta a quello che immagino sia il tuo intento ancora meglio-presumibilmente non vuoi che qualcosa del genere superi il test:

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

Ma sarà nella versione attuale.

Ma nessuno di questi risolve il problema di "illegal start of simple expression", ma corregge la logica e riduce a sedici righe di codice. Il problema qui è che devi decidere quale dovrebbe essere il tuo name se il test che hai appena terminato non riesce.L'approccio più ovvio è quello di utilizzare un Option:

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

Ma a seconda di come si sta utilizzando name, qualche altro approccio può essere più appropriato.

+0

Grazie per la risposta e sottolineando tali problemi, applicherò tali modifiche al codice. Ho modificato la mia domanda per sottolineare che questo è tutto in un completo - per il quale penso (potrebbe essere sbagliato) cambia la natura ternaria dell'istruzione if. – Cowan

Problemi correlati