Scala Option [(A, B)] сопоставление с образцом - PullRequest
5 голосов
/ 17 мая 2011

Я пишу генератор кода Java.

У меня есть неизменяемая карта, которая содержит отображение из java.sql.Types [Int] в кортеж (String, String), где первое значение - это тип Java, авторой пакет Java, из которого можно импортировать тип, если он не импортирован по умолчанию (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))

Я пытаюсь сопоставить шаблон при поиске этой карты, где dataTypejava.sql.Types значение из метаданных базы данных:

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)
  }

Компилятор выдаёт мне ошибку при первом case (начинается с 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Я не уверен, что не так.

Ответы [ 2 ]

11 голосов
/ 17 мая 2011

Some не извлекает до двух значений, а извлекает до одного.Если вы хотите сопоставить какую-то пару, то вам нужно удвоить скобки:

case Some( (jType, Some(iType)) ) => (jType, iType)

Было бы неплохо, если бы вы могли использовать соглашение о стрелках в качестве экстрактора, но это, к сожалению, не кажетсяна работу:

case Some(jType -> Some(iType)) => (jType, iType)

ОБНОВЛЕНИЕ

В качестве альтернативы, если вы используете опцию, вы можете воспользоваться ее монадической природой и просто отобразить объект:

val tpes = SqlTypesToJavaTypeNames.get(dataType)
val (javaType, importType) =
  tpes map { case (a,b) => (a, b.orNull) } getOrElse { throw ... }
6 голосов
/ 17 мая 2011

Вам не хватает внутренних паренов (потому что у вас есть Option[(A, B)]:

case Some( (jType, Some(iType)) ) => 
case Some( (jType, _) )           =>
case None                         =>

Судя по виду вашего метода, кажется, что вы могли бы упростить еще больше:

SqlTypesToJavaTypeNames.get(dataType) map { case (jType, maybeIType) => jType -> maybeIType.orNull } getOrElse error("Unmapped : " + dataType)
...