模式匹配中的隐式 ClassTag [英] Implicit ClassTag in pattern matching

查看:36
本文介绍了模式匹配中的隐式 ClassTag的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

举个例子:

import scala.reflect._

def get[T](list: List[Any])(implicit tag: ClassTag[T]) = {
  list.flatMap {
    case element: T => Some(element)
    case _ => None
  }
}

我可以使用 get() 从列表中获取 T 类型的值(例如 get[String](list) 将给出我该列表中的所有字符串).

I can use get() to get values of type T from a list (e.g. get[String](list) will give me all strings from that list).

现在,我明白编译器会自动提供 ClassTag[String] 类型的值.我也知道 ClassTag 是一个类型类,在幕后的某个地方有一段代码表示 implicitly[ClassTag[T]].getRuntimeClass() 或其他什么.

Now, I understand that compiler provides the value of type ClassTag[String] automatically. I also understand that ClassTag is a type class, and somewhere behind the curtain there's a piece of code that says implicitly[ClassTag[T]].getRuntimeClass() or whatever.

但如果是这样,为什么我们可以在没有 class 标签的情况下进行模式匹配(在这种情况下我们无法区分已擦除的类型)?我的意思是,如果我声明一个隐式参数(由编译器自动提供),我会得到一个行为,但如果我不这样做,我会得到不同的行为?

But if that's so, how come we can pattern match without the class tag (we just can't differentiate between erased types in that case)? I mean, how is it achieved that, if I declare an implicit parameter (which is automatically provided by the compiler), I get one behavior, but if i don't I get a different behavior?

推荐答案

编译器会自动将你的代码大致翻译成这样:

The compiler automatically translates your code roughly to this:

  def get[T](list: List[Any])(implicit tag: ClassTag[T]) = list.flatMap {
    case (element @ tag(_: T)) => Some(element)
    case _ => None
  }

ClassTag 有一个 unapply(x: Any) 重载,允许它对值进行模式匹配.我已经清理了从 reify 获得的树,只显示相关部分,但这会显示完整的树:

ClassTag has an unapply(x: Any) overload that allows it to pattern match on values. I've cleaned up the tree obtained from reify to only show the relevant parts, but this will show you the full tree:

scala.reflect.runtime.universe.reify { 
    def get[T](list: List[Any])(implicit tag: ClassTag[T]) = {
      list.flatMap {
        case element: T => Some(element)
        case _ => None
      }
    }
}

另见 scaladoc:

编译器通过将 (_: T) 类型模式包装为 ct(_: T) 来尝试将模式匹配中的未检查类型测试转换为已检查类型测试,其中ctClassTag[T] 实例.在调用其他提取器之前所需的类型测试也同样处理.SomeExtractor(...) 变成 ct(SomeExtractor(...)) if TSomeExtractor.unapply(x:T) 是不可检查的,但是我们有一个 ClassTag[T] 的实例.

The compiler tries to turn unchecked type tests in pattern matches into checked ones by wrapping a (_: T) type pattern as ct(_: T), where ct is the ClassTag[T] instance. Type tests necessary before calling other extractors are treated similarly. SomeExtractor(...) is turned into ct(SomeExtractor(...)) if T in SomeExtractor.unapply(x: T) is uncheckable, but we have an instance of ClassTag[T].

这篇关于模式匹配中的隐式 ClassTag的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆