在Scala中使用方法名称"x"和隐式转换

flr*_*rnb 4 scala compilation implicit-conversion

假设我想通过提供这样的隐式转换来添加用于计算两个3元组的向量积的工具:

import scala.math.Numeric.Implicits._

case class Vector3[T : Numeric](a : T, b : T, c : T) {
    def x(v : Vector3[T]) = (b*v.c - c*v.b, c*v.a - a*v.c, a*v.b - b*v.a)
}

implicit def toVector[T : Numeric](p : (T,T,T)) = Vector3(p._1, p._2, p._3)
Run Code Online (Sandbox Code Playgroud)

我希望编译以下代码安静:

       (1,0,0) x (0,1,0) // does not compile
Run Code Online (Sandbox Code Playgroud)

但是,它会产生错误,"x"不是(Int,Int,Int)的成员.手动创建包装类的实例:

Vector3(1,0,0) x (0,1,0) // compiles
Run Code Online (Sandbox Code Playgroud)

如果我使用另一个方法名称而不是'x',比如'y',隐式转换也可以:

       (1,0,0) y (0,1,0) // compiles
Vector3(1,0,0) y (0,1,0) // compiles
Run Code Online (Sandbox Code Playgroud)

"x"有什么特别之处?它如何干扰隐式转换机制?

Rex*_*err 6

有什么问题.x?我们去问问吧:

scala> (1,2,3).x
<console>:23: error: type mismatch;
 found   : (Int, Int, Int)
 required: ?{def x: ?}
Note that implicit conversions are not applicable
because they are ambiguous:
 both method tuple3ToZippedOps in object Predef of type
   [T1, T2, T3](x: (T1, T2, T3))runtime.Tuple3Zipped.Ops[T1,T2,T3]
 and method toVector of type
   [T](p: (T, T, T))(implicit evidence$1: Numeric[T])Vector3[T]
 are possible conversion functions from (Int, Int, Int) to ?{def x: ?}
Run Code Online (Sandbox Code Playgroud)

所以你看到了问题:x在另一个转换中被用作底层元组的名称.这是来自runtime.Tuple3Zipped.Ops:

final class Ops[T1, T2, T3](val x: (T1, T2, T3)) extends AnyVal
Run Code Online (Sandbox Code Playgroud)

这可以说是一个错误; 这x是一个令人讨厌的参数,惯例是调用它,repr或者underlying在2.11中它可以被设为私有,以免打扰任何人.