1

我有一个期望 (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))

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

4

3 回答 3

4

在 scala中没有从Intto的隐式转换。Double请参阅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)

由于一致性弱,您可以IntDouble此处使用。

于 2013-07-12T06:53:36.867 回答
2

为了理解这个问题,让我们看一下-Xprint:typer显示的内容:

在第一种情况下,您将 a 传递给testTuple: (String, Int) = (String,2)期望: 的方法testTupleType: (x: (String, Double))Unit,但 Scala 没有从Tuple2[String, Int]to的隐式转换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提到的弱一致性规则,它可以通过调用方法来获取一个Doublefrom 。从 Scala 的角度来看,这不是隐式转换。如果你还记得原始转换是在 C 和 Java 中,早在 Scala 之前InttoDouble

于 2013-07-12T06:52:35.337 回答
1

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

如果你使用val x:Double = 2它应该可以工作。

于 2013-07-12T06:35:02.683 回答