簡體   English   中英

如何在不獲取Scala中的類型擦除編譯器警告的情況下匹配函數簽名

[英]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)
}

有許多方法可行,但沒有一種方法可以直接使用。

一種選擇是使用清單,但您必須定義自己的清單感知匹配變體。 您可以在此處閱讀有關清單的更多信息。 如果你必須做很多這樣的事情,那就是要走的路,雖然這個功能仍然被認為是實驗性的。

如果您的用法相對輕量級,另一個選項是將函數包裝在非泛型的某個類中。 例如,

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM