0

DenseVector と配列の間の双方向の暗黙的な変換を定義する次の (作業中の) スニペットを検討してください。

import scala.reflect.ClassTag
import org.apache.spark.mllib.linalg.Vectors
import breeze.linalg.{DenseVector => BDV}

  implicit def bdvToSeq[T](vect: BDV[T])(implicit ct: ClassTag[T]): Seq[T] = vect.toArray.toSeq

  implicit def arrayToVect(darr: Array[Double]): BDV[Double]
   = new BDV(darr)
  implicit def bdvToArray[T](vect: BDV[T])(implicit ct: ClassTag[T]): Array[T] = vect.toArray

  def add(v1: BDV[Double], v2: BDV[Double]) =
    v1.zip(v2).map { x => x._1 + x._2}

試してみましょう:

scala> arr.allVisitableIndicesActive   // Array to DenseVector implicit conversion
res4: Boolean = true

scala> val d = new BDV(Array(77.7, 88.8, 99.9))
d: breeze.linalg.DenseVector[Double] = DenseVector(77.7, 88.8, 99.9)

今他の方向:

scala> def myArrMethod(arr: Array[Double]) = println(arr.mkString(","))
myArrMethod: (arr: Array[Double])Unit

scala> myArrMethod(d)   // DenseVector to array conversion
77.7,88.8,99.9

次も動作します: darr に注意してください。toSeq

  def norm(darr: Array[Double]): Double = {
    Math.sqrt(darr.toSeq.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
  }

ただし、.toSeq を省略すると、暗黙の衝突が発生します。

scala>   def norm(darr: Array[Double]): Double = {
        Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
       }
<console>:34: error: type mismatch;
 found   : darr.type (with underlying type Array[Double])
 required: ?{def foldLeft(x$1: ? >: Double(0.0)): ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method doubleArrayOps in object Predef of type (xs: Array[Double])scala.collection.mutable.ArrayOps[Double]
 and method arrayToVect of type (darr: Array[Double])breeze.linalg.DenseVector[Double]
 are possible conversion functions from darr.type to ?{def foldLeft(x$1: ? >: Double(0.0)): ?}
           Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
                     ^
<console>:34: error: value foldLeft is not a member of Array[Double]
           Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})

ただし、「.toSeq」を明示的に配置しないことをお勧めします。

だから私の質問は次のとおりです: Predef.toSeqが明確な勝者になるように適切な優先順位を設定する方法-上で定義されたカスタムの優先度の低い暗黙の前に常に試行されましたか?

4

1 に答える 1

1

すべての暗黙的な変換をオブジェクトに抽出し、必要な場所にのみインポートできます

trait BDVImplicits {
  implicit def bdvToSeq[T](vect: BDV[T])(implicit ct: ClassTag[T]): Seq[T] =
    vect.toArray.toSeq

  implicit def arrayToVect(darr: Array[Double]): BDV[Double] =
    new BDV(darr)

  implicit def bdvToArray[T](vect: BDV[T])(implicit ct: ClassTag[T]): Array[T] =
    vect.toArray
}

object BDVImplicits extends BDVImplicits

たとえば、「ノルム」メソッドを Utils に配置し、暗黙的にインポートしない場合は問題ありません。Util メソッドを呼び出すクラスに BDVImplicits._ をインポートするだけです。

この問題の最も簡単な回避策だと思います。

于 2015-01-26T23:16:41.033 に答える