2011-01-06 63 views
3

我回答一個問題關於Defining a Map from String to Function in Scala地圖的功能而導致Function1[_, String]我相信這是正確的,只要打字的問題,但可能是無用的,因爲我不知道如何調用這個函數:如何在Scala中調用Function1 [_,String]?

scala> def f(x: Int) = x.toString 
f: (x: Int)java.lang.String 

scala> f(8) 
res0: java.lang.String = 8 

scala> val g: Function1[_, String] = f _ 
g: Function1[_, String] = <function1> 

scala> g(8) 
<console>:8: error: type mismatch; 
found : Int(8) 
required: _$1 where type _$1 
     g(8) 
     ^

scala> val h: Function1[Int, String] = g 
<console>:7: error: type mismatch; 
found : (_$1) => String where type _$1 
required: (Int) => String 
     val h: Function1[Int, String] = g 

有什麼方法可以使用g

+0

g.asInstanceOf [Function1 [Int,String]](8)的作品,但我不認爲這是一個很好的答案...不是有任何。 – pedrofurla 2011-01-06 17:58:16

+0

假設[另一個問題]的語法(http://stackoverflow.com/questions/4617660/defining-a-map-from-string-to-function-in-scala)(不是你的答案,但實際的原始問題)實際上起作用了,調用地圖中函數的代碼是什麼樣的?在執行Map查找之後,他打算如何將正確的類型發送給正確的功能? – 2011-01-06 18:02:30

回答

3
scala> g.asInstanceOf[Any => String](5) 
res3: String = 5 

這將工作,因爲所有功能擦除相同的東西:Function1[AnyRef, AnyRef]。當你指定它爲Any,然後傳遞一個AnyVal將自動對它進行調用(它將在方法中自動解除裝箱)。

但是,您必須傳遞正確的參數類型。否則...

scala> g.asInstanceOf[Any => String](true) 
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Integer 
1

我會說,這就像如果你投String類型的對象爲Any,如果你想使用String定義,你必須強制轉換爲String的方法。

您將函數作爲一個函數接受存在類型的參數(這是類型上下文中的_意味着什麼),因此您不能將其用作需要Int的函數。要將它作爲一個需要使用Int的函數,您必須將其恢復。

時,圖案的集合或其他通用類匹配存在同樣的問題:

def firstLength(collection: Any): Int ={ 
    collection match { 
    // this is how you would have liked to write it 
    // case list: List[String] => list.head.length 
    // case map: Map[String, String] => map.values.head.length 
    // but this is how you have to write it because of type erasure 
    case list: List[_] => list.asInstanceOf[List[String]].head.length 
    case map: Map[_, _] => map.asInstanceOf[Map[String, String]].values.head.length 
    } 
} 

類型信息不存在,所以你不能匹配List[String],而是你必須匹配對存在型List[_](對於你如何說這可能是錯誤的,它不是存在主義的泛型,我認爲)然後施展。這或多或少正是您遇到的問題,您所處的類型已被擦除,並且無法將其恢復(除非您可以使用與ClassManifest相同的技巧,以便在案例中繞過類型擦除像上面的那樣[但實際上並非如此,因爲它有點草率])。

相關問題