Scala Mappa Filtro: proiezione non può essere assegnato ad un riferimento Map
-
09-09-2019 - |
Domanda
Il seguente codice:
var m: Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = m filterKeys { s => s.length < 3 }
non può essere compilato. Ottengo il seguente errore:
errore: tipo non corrispondente
trovato: collection.this.Map.Projection [scala.this.Predef.String, scala.this.Int]
richiesta: collection.this.Map [scala.this.Predef.String, scala.this.Int]
m = m Filtro {s => s.length <3}
Io non capisco questo come in base al scaladoc di un Projection[A,B]
si estende il tratto Map[A,B+]
. Cioè, una proiezione è una mappa .
Ho pensato che potrebbe essere qualcosa a che fare con il tipo controvariante B
ma se uso Any
invece di Int
, ancora non la compilazione. Che cosa mi manca? La soluzione è quella di fare:
var m: Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = Map(m filterKeys { s => s.length < 3 } toSeq : _ *)
ma questo sembra poco elegante per me.
Soluzione
OK - questo è stato capito, con l'aiuto della console Scala:
scala> var m = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map(A -> 1, BB -> 2, CCC -> 3)
Quindi, il tipo di inferenza è inferire il tipo di m come una mappa immutabile. Il seguente codice compilerà OK:
var m: collection.Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = m filterKeys { s => s.length < 3 }
Tuttavia, questo non è di grande aiuto, come la mappa non può essere aggiunto a in un modo tale da restituire un collection.Map
. Credo che avrebbero dovuto ignorato il metodo ++
ereditato da Iterable
con Map
come tipo di ritorno.
Qualcuno potrebbe commentare su questo? Cosa usare un collection.Map
?
Altri suggerimenti
Sono curioso perché si vuole m sia var anziché val - se non stai cercando di riassegnare la mappa a se stesso, le cose sembrano funzionare bene, come mostrato nella repl, e questo è più in linea con la filosofia alla Scala di immutabilità preferire, se possibile:
scala> val m = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map((A,1), (BB,2), (CCC,3))
scala> val n = m filterKeys { s => s.length < 3 }
n: scala.collection.immutable.Map[java.lang.String,Int] = Map((A,1), (BB,2))
vedo che la questione è un po 'vecchio, è possibile che il comportamento che stai vedendo è diverso in Scala 2.8 data la maggiore refactoring delle classi collezioni.