4

越來越類型消除編譯器警告匹配任何人都可以重新編寫此代碼做同樣的事情,但沒有任何編譯器警告,請: -我怎麼能一個函數簽名,而不在斯卡拉

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") 
    } 

    } 
} 

千thankyous

Keith

更新!!!!對不起,這是一個真正的散列。它我的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 

再次感謝

基思

回答

0
+0

嗨 我已經採取了看那個。我嘗試了最佳答案。接下來的困難是我想調用這個函數。 如果我改變代碼來實際調用下面的函數,我得到一個編譯器錯誤。有誰知道我怎麼能解決這個 對象TestTypeErasure { 高清doTest(參數:任何)= { 參數匹配{ 情況下功能:功能1 [_,_] =>函數( 「什麼」) } } 高清主(參數:數組[字符串]){} } 再次感謝 基思 – Keith 2010-01-25 15:42:33

3

您可以使用Manifests捕獲類型信息。 (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 

對於斯卡拉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) 
} 
+0

只是注意,您需要的Scala 2.8本。 – retronym 2010-01-25 18:18:46

+0

@retronym否,這在2.7.7中有效。 Manifest應該自2.7.2開始提供。 – 2010-01-25 18:35:20

0

有多種方法可能工作,這些都不那麼簡單。

一個選擇是使用清單,但是你必須定義你自己的清單感知的匹配變體。您可以閱讀更多關於清單here。如果你必須做很多這樣的事情,那將是一條路,儘管這個特徵仍然被認爲是實驗性的。

另一種選擇是,如果您的使用量相對較輕,則將該函數包裝在某些非通用類中。例如,

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包裝器,它仍然會有點笨重(並且它不是高性能的)。

(編輯補充清單鏈接我失蹤了。)