I am writing a Java code generator.
I have an immutable Map that contains a mapping from java.sql.Types
[Int] to a tuple of (String, String)
where the first value is a Java type and the second a Java package from which to import the type if it is not imported by default (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))
I am trying to pattern match on a search of this map, where dataType
is the java.sql.Types
value from a database metadata:
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)
}
The compiler is giving me an error on the first case
(starts with 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])]
I'm not sure what is wrong.
Pattern matching is the second most widely used feature of Scala, after function values and closures. Scala provides great support for pattern matching, in processing the messages. A pattern match includes a sequence of alternatives, each starting with the keyword case.
For example, x* matches any number of x characters, [0-9]* matches any number of digits, and . * matches any number of anything. A regular expression pattern match succeeds if the pattern matches anywhere in the value being tested.
Scala's pattern matching statement is most useful for matching on algebraic types expressed via case classes. Scala also allows the definition of patterns independently of case classes, using unapply methods in extractor objects.
Pattern matching tests whether a given value (or sequence of values) has the shape defined by a pattern, and, if it does, binds the variables in the pattern to the corresponding components of the value (or sequence of values). The same variable name may not be bound more than once in a pattern.
Some
doesn't extract to two values, it extracts to one. If you want to match some pair, then you need to double-up on the parentheses:
case Some( (jType, Some(iType)) ) => (jType, iType)
It would be nice if you could use the arrow convention as an extractor, but that sadly doesn't seem to work:
case Some(jType -> Some(iType)) => (jType, iType)
UPDATE
Alternatively, given that you're using an Option, you could take advantage of its monadic nature and simply map over the thing:
val tpes = SqlTypesToJavaTypeNames.get(dataType)
val (javaType, importType) =
tpes map { case (a,b) => (a, b.orNull) } getOrElse { throw ... }
You are missing the inner parens (because you have an Option[(A, B)]
:
case Some( (jType, Some(iType)) ) =>
case Some( (jType, _) ) =>
case None =>
From the looks of your method, it seems like you could simplify even more:
SqlTypesToJavaTypeNames.get(dataType) map { case (jType, maybeIType) => jType -> maybeIType.orNull } getOrElse error("Unmapped : " + dataType)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With