Scala Opção[(A, B)] correspondência de padrão
-
14-11-2019 - |
Pergunta
Eu estou escrevendo um gerador de código Java.
Eu tenho uma imutável Mapa que contém um mapeamento de java.sql.Types
[Int] para uma tupla de (String, String)
onde o primeiro valor é um tipo Java e o segundo um pacote Java a partir do qual importar o tipo se ele não é importado por padrão (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))
Eu estou tentando corresponder ao padrão em uma pesquisa do mapa, onde dataType
é o java.sql.Types
valor a partir de um banco de dados de metadados:
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)
}
O compilador está me dando um erro no primeiro case
(começa com 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])]
Eu não tenho certeza do que é errado.
Solução
Some
não extrair os dois valores, ele extrai a um.Se você deseja corresponder par de alguns, então você precisa de dobrar-se sobre os parênteses:
case Some( (jType, Some(iType)) ) => (jType, iType)
Seria bom se você poderia usar a seta para a convenção como um extractor, mas que, infelizmente, não parecem funcionar:
case Some(jType -> Some(iType)) => (jType, iType)
ATUALIZAÇÃO
Em alternativa, dado que você está usando uma Opção, você pode tirar vantagem da sua monádico natureza e simplesmente mapa sobre a coisa:
val tpes = SqlTypesToJavaTypeNames.get(dataType)
val (javaType, importType) =
tpes map { case (a,b) => (a, b.orNull) } getOrElse { throw ... }
Outras dicas
Você está ausente o interior parens (porque tem uma Option[(A, B)]
:
case Some( (jType, Some(iType)) ) =>
case Some( (jType, _) ) =>
case None =>
A partir da aparência de seu método, parece que é possível simplificar ainda mais:
SqlTypesToJavaTypeNames.get(dataType) map { case (jType, maybeIType) => jType -> maybeIType.orNull } getOrElse error("Unmapped : " + dataType)