我正在使用Scala 2.10,并且发现在使用泛型参数的类型推断时我认为是奇怪的行为。考虑下面的例子(注意i
仅仅是一个虚拟变量):Scala通用类型推断与ClassTag不一致
scala> import scala.reflect.{ClassTag,classTag}
|
| def broken[T : ClassTag](i : Int) : List[T] = {
| println("ClassTag is : " + classTag[T])
| List.empty[T]
| }
import scala.reflect.{ClassTag, classTag}
broken: [T](i: Int)(implicit evidence$1: scala.reflect.ClassTag[T])List[T]
scala> broken(3)
ClassTag is : Nothing
res0: List[Nothing] = List()
scala> val brokenVal : List[String] = broken(3)
ClassTag is : Nothing
brokenVal: List[String] = List()
呼叫broken(3)
似乎一致,在打印语句中的功能与推断ClassTag
同意。
但是,第二种说法是,编译器推断ClassTag
,并在函数内部打印的内容与实际返回类型是什么不一致。
我本来希望编译器能从类型声明中推出ClassTag
,即List[String]
。这是不正确的?有人可以启发我吗?
这里的某些其它方面:我实际使用classtag在一些代码(这里没有显示)来筛选集合,这显然失败的时候我不指定T
明确,因为它是比较反对Nothing
类型。
我实际上使用rx Observables,它也是协变的,并且遇到了这个问题。我在'collect'语句中使用ClassTag只拾取某种类型的项目。因为我使用类型本身来过滤东西,即'observable collect {case t:T => t}',所以没有任何价值可以作为参数传入,像你说的那样可以解决推理问题。感谢您的反馈意见。 – Luciano
即使在这种情况下,仍然有可能收集类型签名的宏解决方案,但我认为在这里使用宏是矫枉过正的。只需省略变量类型并明确指定'[T]'。 – Maxim