[英]How can I match a function signature without getting type erasure compiler warnings in Scala
任何人都可以重新編寫此代碼來做同樣的事情,但沒有任何編譯器警告請: -
object TestTypeErasure {
def main(args:Array[String]) {
def myFunction(myObject:Any):Boolean = {
true
}
val myVariable: (Any => Boolean) = myFunction
myVariable match {
case function:(Any => Boolean) => println("Match")
}
}
}
千萬
基思
更新!!!! 抱歉打算這個真正的哈希。 這是我關於SO的第一個問題
只是為了讓大師們知道我嘗試了一些與此無關的東西也無濟於事: - (無法編譯)
object TestTypeErasure {
def doTest(parameter: Any) = {
parameter match {
case function:Function1[_, _] => function("Whatever")
}
}
def main(args:Array[String]) {
}
}
我收到錯誤: -
TestTypeErasure.scala:6: error: type mismatch;
found : java.lang.String("Whatever")
required: _
case function:Function1[_, _] => function("Whatever")
^
one error found
再次感謝
基思
您可以使用清單捕獲類型信息。 (T,R在這里是不變的,以保持簡單。)
import scala.reflect._
def matchFunction[T,R](f: Function1[T,R], t : T)(implicit mt : Manifest[T], mr : Manifest[R]) = {
val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t)
else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t)
else "Unknown " + f(t)
println(result)
}
scala> matchFunction((x : Int) => x + 1, 1)
int, int 2
scala> matchFunction((x : Any) => true, 1 : Any)
any, boolean true
scala> matchFunction((x : Boolean) => ! x, false)
Unknown
對於Scala 2.8,可以使用上下文邊界,刪除兩個隱式參數:
import scala.reflect._
def matchFunction[T: Manifest,R : Manifest](f: Function1[T,R], t : T) = {
val mt = implicitly[Manifest[T]]
val mr = implicitly[Manifest[T]]
val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t)
else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t)
else "Unknown " + f(t)
println(result)
}
看看這個問題: 模式匹配scala中的零參數函數:通過警告神秘化
有許多方法可行,但沒有一種方法可以直接使用。
一種選擇是使用清單,但您必須定義自己的清單感知匹配變體。 您可以在此處閱讀有關清單的更多信息。 如果你必須做很多這樣的事情,那就是要走的路,雖然這個功能仍然被認為是實驗性的。
如果您的用法相對輕量級,另一個選項是將函數包裝在非泛型的某個類中。 例如,
object Example {
def hasString(a:Any) = (a!=null && a.toString.length>0)
case class AnyImpliesBoolean(f: (Any) => Boolean) { }
implicit def callAIB(aib: AnyImpliesBoolean) = aib.f
def callWrapped(a: Any) {
a match {
case aib: AnyImpliesBoolean => println( aib("Check") )
case _ => println("(Nothing)")
}
}
def tryMe() {
val has = AnyImpliesBoolean(hasString _)
callWrapped( has )
callWrapped("foo")
callWrapped((s:String)=>true)
}
}
scala> Example.tryMe
true
(Nothing)
(Nothing)
如果要包裝幾個不同的函數,但不包含太多函數,則可以創建基類WrappedFunction,然后使用AnyImpliesBoolean等函數擴展WrappedFunction。
另一種選擇是不實際傳遞函數,而是使用反射來傳遞java.lang.Methods。 方法知道他們的類型。 即使有一些漂亮的Scala包裝器,它仍然會有點笨重(而且它不是高性能)。
(編輯添加我遺漏的清單鏈接。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.