"安全" scala中的模式匹配

时间:2015-03-26 16:49:07

标签: scala scala-macros

我正在开发一个涉及从Map[String, Any]到一些案例类的大量序列化/反序列化的项目。我们通常知道密钥的类型是什么,因此我们使用unchecked并指出其他地方没有会导致ClassCastException的错误,就像在这个简单的示例中一样:

def myIntParser(in: Map[String, Any]): Map[String, Int] = in match {
  case out: Map[String, Int @unchecked] => out
}

当然,这是scala,我相信我们可以做得更好。我的问题是如何编写以下函数:

// Returns Some(out) if 'in' can be safely cast as T,
// or None if in's type is not upper-bounded by T.
def safeCast[T: TypeTag](in: Any): Option[T] = ???

为了简化,我们的应用程序仅使用原始类型,地图,列表,选项和案例类,对其字段具有相同的限制。遍历所有结构,拆包等的成本被认为是微不足道的。

这是我目前的尝试,在SO上使用其他一些答案。它失败了,因为我不知道如何将对象的类与类型符号进行比较:

import scala.reflect.runtime.universe._
import scala.reflect._

// For early return
class CastFailException extends Exception("")

@throws[CastFailException]
def safeCastInternal[T](x: Any)(implicit ttag: TypeTag[T]): T = {
  val ev = typeOf[T]

  x match {
    case it: Iterable[_] if ev <:< typeOf[Iterable[Any]] =>
      val innerTpes = ev match {
        case TypeRef(_, _, args) => args
      }
      val innerTpe = innerTpes.headOption.getOrElse(throw new CastFailException)
      val tt = backward[Any](innerTpe)
      it.toList.map(x => safeCastInternal(x)(tt)).asInstanceOf[T]
    case y => ???
  }
}

val universe = scala.reflect.runtime.universe
val mirror = runtimeMirror(getClass.getClassLoader)
// From another SO question
def backward[T](tpe: Type): TypeTag[T] =
  TypeTag(mirror, new api.TypeCreator {
    def apply[U <: api.Universe with Singleton](m: api.Mirror[U]) =
      if (m eq mirror) tpe.asInstanceOf[U # Type]
      else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.")
  })

提前致谢!

0 个答案:

没有答案