Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Option[(A, B)] pattern matching

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.

like image 842
Ralph Avatar asked May 16 '11 20:05

Ralph


People also ask

Does Scala have pattern matching?

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.

What is pattern matching give an example?

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.

What is case class and pattern matching in Scala?

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.

How pattern matching works in a function's parameter list?

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.


2 Answers

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 ... }
like image 133
Kevin Wright Avatar answered Sep 19 '22 14:09

Kevin Wright


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)
like image 24
oxbow_lakes Avatar answered Sep 20 '22 14:09

oxbow_lakes