2013-07-12 22 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