Scala Option [(A, B)] correspondance de modèle
-
14-11-2019 - |
Question
J'écris un générateur de code Java.
J'ai une carte immuable qui contient un mappage de java.sql.Types
[Int] à un tuple de (String, String)
où la première valeur est un type Java et la seconde un package Java à partir duquel importer le type s'il n'est pas importé par défaut (java.lang
):
val SqlTypesToJavaTypeNames =
Map(Types.BIGINT -> ("Long", None),
Types.BINARY -> ("byte[]", None),
Types.BIT -> ("Boolean", None),
Types.BOOLEAN -> ("Boolean", None),
Types.CHAR -> ("String", None),
Types.DATE -> ("Date", Some("java.sql.Date")),
Types.DECIMAL -> ("BigDecimal", Some("java.math.BigDecimal")),
Types.DOUBLE -> ("Double", None),
Types.FLOAT -> ("Float", None),
Types.INTEGER -> ("Integer", None),
Types.LONGNVARCHAR -> ("String", None),
Types.LONGVARCHAR -> ("String", None),
Types.NCHAR -> ("String", None),
Types.NUMERIC -> ("BigDecimal", None),
Types.NVARCHAR -> ("String", None),
Types.REAL -> ("Float", None),
Types.SMALLINT -> ("Short", None),
Types.SQLXML -> ("String", None),
Types.TIME -> ("Time", Some("java.sql.Time")),
Types.TIMESTAMP -> ("Timestamp", Some("java.sql.Timestamp")),
Types.TINYINT -> ("Byte", None),
Types.VARCHAR -> ("String", None))
J'essaie de faire correspondre un modèle lors d'une recherche sur cette carte, où dataType
est le java.sql.Types
valeur provenant des métadonnées d'une base de données :
val (javaType, importType) =
SqlTypesToJavaTypeNames.get(dataType) match {
case Some(jType, Some(iType)) => (jType, iType)
case Some(jType, None) => (jType, null)
case None => throw new IllegalStateException("Unknown translation to Java type for SQL type " + dataType)
}
Le compilateur me donne une erreur au premier case
(commence avec case Some(jType, Some(iType))
): error: wrong number of arguments for <none>: (x: (java.lang.String, Option[java.lang.String]))Some[(java.lang.String, Option[java.lang.String])]
Je ne suis pas sûr de ce qui ne va pas.
La solution
Some
n'extrait pas en deux valeurs, il extrait en une seule.Si vous souhaitez faire correspondre une paire, vous devez alors doubler les parenthèses :
case Some( (jType, Some(iType)) ) => (jType, iType)
Ce serait bien si vous pouviez utiliser la convention des flèches comme extracteur, mais cela ne semble malheureusement pas fonctionner :
case Some(jType -> Some(iType)) => (jType, iType)
MISE À JOUR
Alternativement, étant donné que vous utilisez une option, vous pouvez profiter de sa nature monadique et simplement cartographier la chose :
val tpes = SqlTypesToJavaTypeNames.get(dataType)
val (javaType, importType) =
tpes map { case (a,b) => (a, b.orNull) } getOrElse { throw ... }
Autres conseils
Il vous manque les parenthèses intérieures (parce que vous avez un Option[(A, B)]
:
case Some( (jType, Some(iType)) ) =>
case Some( (jType, _) ) =>
case None =>
D'après l'apparence de votre méthode, il semble que vous pourriez simplifier encore plus :
SqlTypesToJavaTypeNames.get(dataType) map { case (jType, maybeIType) => jType -> maybeIType.orNull } getOrElse error("Unmapped : " + dataType)