【问题标题】:Scala Option[(A, B)] pattern matchingScala Option[(A, B)] 模式匹配
【发布时间】:2011-05-16 20:57:45
【问题描述】:

我正在编写一个 Java 代码生成器。

我有一个不可变的 Map,其中包含从 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))

我正在尝试在搜索此地图时进行模式匹配,其中 dataType 是数据库元数据中的 java.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])]

我不知道出了什么问题。

【问题讨论】:

  • 您缺少括号。 Some(x,y) 不是 Some((x,y))
  • 我删除了问题中的 2.9.0,因为这并不特定于新版本的 scala

标签: scala pattern-matching scala-option


【解决方案1】:

Some 不会提取到两个值,而是提取到一个。如果你想匹配一些配对,那么你需要在括号上加倍:

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

如果您可以使用箭头约定作为提取器,那就太好了,但遗憾的是,这似乎不起作用:

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

更新

或者,如果您使用的是 Option,您可以利用它的一元性质并简单地映射该事物:

val tpes = SqlTypesToJavaTypeNames.get(dataType)
val (javaType, importType) =
  tpes map { case (a,b) => (a, b.orNull) } getOrElse { throw ... }

【讨论】:

  • 你大概可以为->定义你自己的提取器
  • @oxbow_lakes:我可以,但在这种情况下我有一个更好的主意:)
  • @Kevin Wright:非常好,尤其是使用map 的答案。我不知道Option[A] 的功能。需要阅读 Scaladocs。谢谢。还要感谢 oxbow_lakes。
  • 只需阅读 Option[+A] 的 Scaladocs。我没有意识到在 match 中使用 Optionnot 惯用的。去图...
【解决方案2】:

您缺少内部括号(因为您有一个 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)

【讨论】:

  • 再说一次,为什么Option.fold(或mapOrElse,或任何你想称呼它的名字)不在标准库中?
猜你喜欢
  • 2012-02-08
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多