2013-07-12 48 views
1

我有希望(字符串,雙)爲參數的Scala的元組不顯示類型不匹配,如果傳遞參數直列

scala> def testTupleType(x: (String, Double)) = {} 
testTupleType: (x: (String, Double))Unit 

scala> val x: Int = 2 
x: Int = 2 

然後我試圖通過類似的參數到testTupleType方法的方法:

scala> val testTuple = ("String", x) 
testTuple: (String, Int) = (String,2) 

scala> testTupleType(testTuple) 
<console>:11: error: type mismatch; 
found : (String, Int) 
required: (String, Double) 
       testTupleType(testTuple) 

它按預期顯示錯誤。但是當我通過內聯的參數:

scala> testTupleType(("String", x)) 

沒有任何錯誤!我不知道這是因爲這裏的隱式轉換嗎?

回答

4

在斯卡拉沒有從IntDouble的隱式轉換。見3.5.3 弱一致性SLS

如果testTupleType(testTuple)錯誤包含所有信息:(String, Int)不是(String, Double)

隨着 「內聯」 參數:

testTupleType(("String", x)) 

這意味着:

testTupleType(Tuple2.apply("String", x)) 

方法apply接受2個型參數:

def apply[T1, T2](_1: T1, _2: T2): (T1, T2) 

testTupleType接受(String, Double),所以結果類型的apply(T1, T2))應該是(String, Double)

testTupleType(Tuple2.apply[String, Double]("String", x)) 

或:類型推斷後

val a: (String, Double) = Tuple2.apply[String, Double]("String", x) 
testTupleType(a) 

由於弱一致性,您可以使用Int作爲Double這裏。

+0

謝謝,我讀到了關於弱一致性的內容,但仍然模糊了它在這裏的應用。這是將(String,Int)轉換爲(String,Double)的apply方法嗎?轉換究竟如何? – Pham

+0

@Pham:具有指定類型參數的方法'Tuple2.apply [String,Double]'接受'Double'作爲第二個參數,並且可以將'Int'傳遞給接受'Double'的方法:'def test [T](d: T)= d' =>'test [Double]((1:Int))'。 – senia

1

該問題是由於您的代碼取決於隱式轉換,在這種情況下,當您傳遞testTuple內聯時不會發生這種情況。

如果您使用val x:Double = 2它應該工作。

+0

問題是我使用x:Int的事件,它仍然工作,如果參數傳遞「inline」 – Pham

2

要理解這個問題,讓我們看看-Xprint:typer顯示:

在你傳遞一個testTuple: (String, Int) = (String,2)成期望方法第一種情況:testTupleType: (x: (String, Double))Unit,但Scala沒有一個隱含的皈依從Tuple2[String, Int]Tuple2[String, Double]:請記住,(String,Int)只是調用Tuple2.apply的編譯器的語法糖。

那麼爲什麼秒片段的作品?因爲Scala desugars到Tuple2[String, Double]這樣的:

private[this] val res1: Unit = testTupleType(scala.Tuple2.apply[String, Double]("String", x.toDouble)); 
<stable> <accessor> def res1: Unit = res1 

要總結,在第一種情況下,你已經有了一個Tuple2 [字符串,INT]和Scala沒有一個隱含的皈依爲它Tuple2 [字符串,雙] ,但你可以讓你自己:

implicit def tsi2tdi(t: Tuple2[String, Int]): Tuple2[String, Double] = (t._1, t._2.toDouble) 

,並在秒的情況下它看到你有一個字符串和一個int,你需要將它們轉換爲Tuple2[String, Double]

更新

沒有,這就是所謂的不被apply方法,它是由編譯器調用。編譯Scala執行不同的分析階段,其中之一稱爲typer。當scalac看到,那麼你必須在代碼中Int,但你想要得到的是一個Double值,它知道,根據塞尼亞提到的弱一致性規則,它可以通過調用toDouble方法得到Int一個Double 。這不是Scala觀點中的隱式轉換。如果你還記得原始轉換是在C和Java,早在斯卡拉

+0

所以你的意思是應用方法實際上調用toDouble()參數? – Pham

+0

@Pham在答案中增加了一些信息 – 4lex1v

+0

謝謝你現在更清楚了 – Pham