2015-04-30 14 views
6

In una chiamata di prova una funzione di terze parti che restituisce un Option[Any]. So che se questa funzione restituisce un Map, è un Map[String, Any]. In questo caso, voglio verificare i singoli elementi della mappa.Scala: come sopprimere gli avvertimenti non selezionati/eseguire la corrispondenza dei modelli delle mappe correttamente?

theFunction(...) match { 
    case Some(m: Map[String, Any]) => 
    m("some key") match { 
     case some_condition => ... (my check) 
    } 
    case _ => fail("Invalid type") 
} 

Ma il compilatore avverte che case Some(m: Map[String, Any]) è deselezionato. Quando uso lo Map[_,_], invece, il compilatore viene richiamato nel punto in cui controllo lo m("some key").

Come si sopprime questo avviso, o meglio: come si esegue questo controllo correttamente? L'unico approccio mi viene in mente è qualcosa di simile

theFunction(...) match { 
    case Some(m: Map[_,_]) => 
    val m1: Map[String, Any] = m.toSeq.map(t => t._1.asInstanceOf[String] -> t._2).toMap 
    m1("some key") match { 
     case some_condition => ... (my check) 
    } 
} 

ma ai miei occhi, questo sembra brutto e introduce inutile conversione della mappa per un Seq e viceversa.

+0

Ho accettato la seconda risposta, e uso il mio modo complicato in quanto viene utilizzato in un test, ed è utile avere informazioni più dettagliate sull'errore se qualcosa non dovrebbe essere come previsto. – rabejens

risposta

1

Attualmente non c'è modo di sopprimere questi avvisi in Scala. C'è qualche discussione interessante sull'argomento here. È possibile ignorare l'avviso, o utilizzare asInstanceOf:

m.asInstanceOf[Map[String, Any]]("some key") match { ... } 

Questi tipi di operazioni di runtime sono soggetto a errori, e di solito punta a un sistema di tipo povero. Esistono pochissime situazioni in cui un metodo deve restituire Option[Any]. Quasi ogni uso di Any come tipo di ritorno è una bandiera rossa in Scala.

21

È possibile utilizzare l'annotazione unchecked per sopprimere gli avvisi del compilatore come questi (per le corrispondenze non esaustive e le partite infruttuose a causa della cancellazione dei tipi).

Dal scaladoc:

Un'annotazione per indicare che l'entità annotato non deve essere considerato per i controlli addizionali per il compilatore. Le applicazioni specifiche includono l'annotazione del soggetto di un'espressione di corrispondenza per sopprimere gli avvisi di esaustività e l'annotazione di un argomento di tipo in un caso di corrispondenza per sopprimere gli avvertimenti non controllati.

Tale soppressione deve essere utilizzata con cautela, senza la quale è possibile riscontrare scala.MatchError o java.lang.ClassCastException in fase di esecuzione. Nella maggior parte dei casi, è possibile e dovrebbe indirizzare l'avviso anziché sopprimerlo.

Esempio:

val m: Any = Some(Map("a" -> 1, "b" -> "b")) 
m match { 
    case Some(m: Map[String, Any]) => println("map") 
    case None => println("None") 
} 

<console>:30: warning: non-variable type argument String in type pattern scala.collection.immutable.Map[String,Any] (the underlying of Map[String,Any]) is unchecked since it is eliminated by erasure 
        case Some(m: Map[String, Any]) => println("map") 

possiamo aggiungere il @unchecked annotazione Map[String, Any] all'interno della partita:

m match { 
    case Some(m: Map[String, Any] @unchecked) => println("I'm a map!") 
    case None => println("None") 
} 

// Exiting paste mode, now interpreting. 

I'm a map! 

Non più di avvertimento. Ma questo ovviamente non è più sicuro che consentire l'avvertimento, e potrebbe portare ad alcuni errori di corrispondenza sorprendenti o ClassCastException s.

+1

questo non funziona, l'avviso è ancora lì –

+1

Che versione scala? Funziona in 2.11 –

1

Bene, non sono sicuro, se è correlato alla domanda, ma è possibile dove si desidera aggiungere annotazioni di tipo.

Ad esempio, ho

type H = List[Int] 
def sum_dummy(h: H): Int = { 
    if (isEmpty(h)) throw new NoSuchElementException() 
    else (h:H @unchecked) match { 
     case x::list => x + func(list) 
    } 
} 

si può riscrivere esempio con case Nil utilizzo per la piena scala idiomatica, ma l'ho scritto per esempio tipo di annotazione.

Problemi correlati