如果传递参数内联,Scala Tuple不显示类型不匹配

时间:2013-07-12 04:25:51

标签: scala

我有一个期望(String,Double)作为参数

的方法
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))

没有任何错误!我不知道这是因为这里有隐式转换吗?

3 个答案:

答案 0 :(得分:4)

scala中没有从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

答案 1 :(得分:2)

要了解问题,请查看-Xprint:typer显示的内容:

在第一种情况下,您将testTuple: (String, Int) = (String,2)传递给期望testTupleType: (x: (String, Double))Unit的方法,但Scala没有从Tuple2[String, Int]Tuple2[String, Double]的隐式转换:

val t = Tuple2[String, Int]("a", 2)
val a: (String, Double) = t
<console>:8: error: type mismatch;
 found   : (String, Int)
 required: (String, Double)
       val a: (String, Double) = t
                                 ^

请记住,(String,Int)只是调用Tuple2.apply的编译器的语法糖。

那么为什么秒片段有效呢?因为Scala将其变为Tuple2[String, Double]

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

总结一下,在第一种情况下,你已经有了一个Tuple2 [String,Int],并且Scala没有隐式转换为Tuple2 [String,Double],但是你可以创建自己的:

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

并且在秒的情况下,它看到你有一个String和一个Int,你需要将它们转换为Tuple2[String, Double]

<强>更新

不,它不是由apply方法调用,而是由编译器调用。编译Scala时执行不同的分析阶段,其中一个称为typer。当scalac看到代码中有Int时,您想要得到的是Double值,它知道根据提到的弱一致性规则senia ,它可以通过调用Double方法从Int获得toDouble。这不是Scala观点中的隐式转换。如果你还记得原始转换是在C和Java中,早在Scala之前

答案 2 :(得分:1)

问题是由于您的代码取决于隐式转换,在这种情况下,当您传递testTuple内联时,它不会发生。

如果你使用val x:Double = 2它应该有用。