通过擦除斯卡拉
问题描述:
消除返回类型考虑下面的Scala代码片段:通过擦除斯卡拉
def func(param: Any): Int = param match {
case f: (String => Int) => f("apple")
case i: Int => i
}
println(func((s: String) => s.length))
正常工作,但是,在编译时,我得到以下警告:
<console>:11: warning: non-variable type argument String in type pattern String => Int is unchecked since it is eliminated by erasure
case f: (String => Int) => f("apple")
我怎样才能摆脱此警告讯息?
感谢您的帮助提前!
答
收到消息的原因是因为Java的通用type erasure。在这种情况下,您的Function[String, Int]
类型的功能将与任何Function[A, B]
匹配。
为了摆脱这个警告,你应该使用scala typetags这将允许你区分不同的功能类型。
的代码片段是以下,
import scala.reflect.runtime.universe._
object Answer {
def function[A](param: A)(implicit tt: TypeTag[A]): String = param match {
case f: (String => Int) @unchecked if typeOf[String => Int] =:= typeOf[A] => f("apple").toString
case f: (Int => String) @unchecked if typeOf[Int => String] =:= typeOf[A] => f(32 + 1)
case s: String => s"hello $s"
}
def main (args: Array[String]) {
println(function((s: String) => s.length))
println(function((i: Int) => i.toString))
println(function("world"))
}
}
的关键部分是有一个implicit
TypeTag[A]
它是在编译时,其包括该功能typeOf
需要检查类型的A
针对别的元数据添加。
感谢您的解释和链接!我试图解决警告但失败。现在我对'TypeTag'的含义有了一个理论上的认识,而且我知道'case f:((_)=>(_))=>'不会抱怨。但是,在后一种情况下,'f(...)'会导致编译器错误。请您这么友好地给我一些进一步的提示如何继续?谢谢! –
用代码片段更新。 – yw3410
感谢您的解释性代码!它确实更精确,因为我们现在可以区分String => Int和Int => String。我已经尝试过了,但不幸的是现在有两次同样的警告。 我尝试了以下方法:'type oneParamFuncType = _ => _',并且在两种情况下都使用'case f:oneParamFuncType ...',但是,这会导致函数调用时发生编译器错误。如果没有函数调用,编译器会很高兴。你有没有想法如何将通用'oneParamFuncType'转换为特定的? –